题目链接:
Decode the Tree
题意:
给出一个Prufer序列,求出这个树
思路:
首先要知道Prufer序列。对于任意一个无根树,每次去掉一个编号最小的叶子节点,并保存这个节点所连接的节点所得到的序列就是这棵树的Prufer序列。
读入序列后,遍历1-n,没有进入序列的节点即为叶子节点,序列中某个节点的出现次数就代表这个节点有几个子节点,开一个数组记录这个节点出现次数,然后下一步感觉和拓扑排序差不多,遍历序列,每一次从优先队列中取出最小的叶子节点,然后与序列中的当前点进行匹配,删除这条边,如果这个节点的度数为1,那么就表明这个节点为叶子节点,那么进入队列。
开一个vector保存树
每一次删除边的时候,将叶子节点并入序列当前节点的子节点中,最后dfs输出这个树
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <stack>
#include <queue>
#include <map>
#include <cmath>
#include <algorithm>
#include <sstream>
using namespace std;
const int maxn = 55;
const int inf = 0x7fffffff;
int f[maxn],ans[maxn];
//f[]存Prufer序列,ans存这个点有几个子节点(为0则为叶子节点)
vector <int> vec[maxn];
//存储每个节点相连的子节点
bool cmp(int a,int b)
{
return a < b;
}
void init()
{
for(int i = 0; i < maxn; i++){
vec[i].clear();
}
memset(ans,0,sizeof(ans));
}
void print(int x)
{
printf("(");
printf("%d",x);
int l = vec[x].size();
//vector排序
sort(vec[x].begin(),vec[x].end(),cmp);
for(int i = 0; i < l; i++){
printf(" ");
print(vec[x][i]);
}
printf(")");
}
int main()
{
int n = 0;
string line;
while(getline(cin,line)){
init();
stringstream ss(line);
for(n = 0; ss>>f[n]; n++){
ans[f[n]]++;
}
priority_queue <int,vector<int>,greater<int> > leaf;
for(int i = 1; i <= n; i++){
if(!ans[i]){
leaf.push(i);
}
}
for(int i = 0; i < n; i++){
int temp = leaf.top();
leaf.pop();
vec[f[i]].push_back(temp);
ans[f[i]]--;
if(!ans[f[i]]){
leaf.push(f[i]);
}
}
if(!n){
printf("(1)\n");
}
else{
print(f[n - 1]);
printf("\n");
}
}
}