Prufer Code

1069. Prufer Code

Time limit: 0.25 second
Memory limit: 8 MB
A tree (i.e. a connected graph without cycles) with vertices is given (N ≥ 2). Vertices of the tree are numbered by the integers 1,…,N. A Prufer code for the tree is built as follows: a leaf (a vertex that is incident to the only edge) with a minimal number is taken. Then this vertex and the incident edge are removed from the graph, and the number of the vertex that was adjacent to the leaf is written down. In the obtained graph once again a leaf with a minimal number is taken, removed and this procedure is repeated until the only vertex is left. It is clear that the only vertex left is the vertex with the number N. The written down set of integers (N−1 numbers, each in a range from 1 to N) is called a Prufer code of the graph.
Your task is, given a Prufer code, to reconstruct a tree, i.e. to find out the adjacency lists for every vertex in the graph.
You may assume that 2 ≤ N ≤ 7500

Input

A set of numbers corresponding to a Prufer code of some tree. The numbers are separated with a spaces and/or line breaks.

Output

Adjacency lists for each vertex. Format: a vertex number, colon, numbers of adjacent vertices separated with a space. The vertices inside lists and lists itself should be sorted by vertex number in an ascending order (look at sample output).

Sample

inputoutput
2 1 6 2 6
1: 4 6
2: 3 5 6
3: 2
4: 1
5: 2
6: 1 2
Problem Author: Magaz Asanov
Problem Source: Ural State Univerisity Personal Contest Online February'2001 Students Session
Tags: graph theory  (
hide tags for unsolved problems
)
这题看了很久,一直犹豫着不知道要怎么输入,以前做题一般都是逐个例子输入的,此题仿佛不是。。。后来发现是一次过输入所有数据,然后在处理。
搜索关键词Prufer Code,在维基能发现现成的算法,不过本人用的是笨一点的思路。
思路:对于输入的数列node,遍历之,对于node[i],在他前面未被删除而在他后面不再出现的最小序号对应的节点是node[i]的儿子。一开始用flag数组标记每一个节点的序号在数列中出现的次数,当遍历到node[i]时,若有最小的序号j对应的flag为0,j即与i相邻。由于输出儿子要有序,故而每个节点对应一个最小堆。但由于使用priority_queue是默认从大到小的,故而要自定义比较运算符。
 
AC Code:
#include <iostream>
#include <queue>
#include <cstdio>
#include <cstring>

using namespace std;

const int MAXN = 7503;
int node[MAXN];
int flag[MAXN];  //数字i在数列中出现了flag[i]次

struct Cmp  //自定义运算符
{
    bool operator() (const int& x, const int& y)
    {
        return x > y;
    }
};

priority_queue<int, vector<int>, Cmp> son[MAXN];

int main()
{
    memset(flag, 0, sizeof(flag));
    int n = 1;  //n-顶点数
    //输入
    while(~scanf("%d", &node[n]))
    {
        flag[node[n++]]++;
    }
    //处理:算出每一个节点的儿子,存于堆中
    for(int i = 1; i < n; i++)
    {
        for(int j = 1; j <= n; j++)
        {
            if(!flag[j])
            {
                flag[j] = -1;  //-1表明该节点已经删除
                son[node[i]].push(j);
                son[j].push(node[i]);
                break;
            }
        }
        flag[node[i]]--;
    }
    //输出结果
    for(int i = 1; i <= n; i++)
    {
        printf("%d:", i);
        while(!son[i].empty())
        {
            printf(" %d", son[i].top());
            son[i].pop();
        }
        puts("");
    }
    return 0;
}

 

posted on 2013-07-20 17:33  铁树银花  阅读(669)  评论(0编辑  收藏  举报

导航