Decode the Tree poj2568(Prufer序列)

题目链接:
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");
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值