1 条题解

  • 0
    @ 2025-5-6 1:46:45

    解题思路:

    本题要求根据树的普鲁弗码反推树的结构并以特定格式输出。关键点在于理解普鲁弗码生成规则与逆向恢复逻辑的结合:

    Prufer序列性质:

    每个数字表示当前移除最小叶结点时的父结点编号-

    度与频次的关系:

    结点的出度等于其在Prufer序列中出现的次数加一

    逆向构建逻辑:

    从叶结点出发逐步还原父子关系核心难点

    动态维护叶结点集合:

    使用优先队列实时管理当前可操作叶结点结构化存储

    统计频次与初始化对Prufer序列进行统计:

    count[]count[]数组记录各结点出现次数→degree[x]=count[x]+1degree[x]=count[x] + 1

    C++实现

    #include<iostream>
    #include<stdio.h>
    #include<queue>
    #include<string.h>
    #include<string>
    #include<sstream>
    #include<algorithm>
    #include<vector>
    using namespace std;
    int f[55],ans[55];
    vector<int> vec[55];
    bool cmp(const int &a,const int &b)
    {
      return a<b;
    }
    void dfs(int x)
    {
      printf("(");
      printf("%d",x);
      int l=vec[x].size();
      sort(vec[x].begin(),vec[x].end(),cmp);//vector排序
      for(int i=0;i<l;i++)
      {
      	printf(" ");
      	dfs(vec[x][i]);
      }
      printf(")");
      vec[x].clear();//清空vector以防影响下组数据
    }
    int main()
    {
      int i,n=0;
      string line;
      memset(ans,0,sizeof(ans));
      while(getline(cin,line))//输入'EOF'停止
      {
      	stringstream ss(line);//用sstream类库读取数据
      	for(n=0;ss>>f[n];n++)//
      		ans[f[n]]++;
      	n--;
      		priority_queue<int,vector<int>,greater<int> > leafs;
      		for(i=1;i<=n+1;i++)
      			if(!ans[i]) leafs.push(i);
      		for(i=0;i<=n;i++)
      		{
      			int k=leafs.top();
      			leafs.pop();
      			vec[f[i]].push_back(k);
      			if(--ans[f[i]]==0) leafs.push(f[i]);
      		}
      		if(n!=-1) dfs(f[n]);
      		else printf("(1)");//输入为0
      		printf("\n");
      		memset(ans,0,sizeof(ans));
      }
    }
    
    • 1

    信息

    ID
    1569
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    7
    已通过
    1
    上传者