您的位置:首页 > Web前端

URAL 1069 Prufer Code 树结构脑洞题

2017-07-12 22:11 316 查看


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

一棵树,每次删去编号最小的叶子节点和与其相连的边,每次都记录这个节点的父亲节点编号,直到只剩下根节点。让你还原这棵树。

记录的编号中,没有出现过的节点就是原始树中的叶子节点。因为如果某节点不是叶子节点,则它的子节点被删除时它必定被记录编号。

每次删点选取的是编号最小的叶节点,可以想象,这个被删的节点在之后的所有编号中都不会出现,而这个叶节点的编号又最小,所以每次删掉的是之后的编号中没有出现过的编号最小的根节点。

而编号最小可以用优先队列维护,不断把之后编号中未出现的编号加入队列。

#include <cstdio>
#include <iostream>
#include <vector>
#include <string.h>
#include <map>
#include <algorithm>
#include <queue>
#include <math.h>
#include <cmath>
#define mem(a) memset(a,0,sizeof(a))
using namespace std;
typedef long long ll;
const int maxn=8005;
int a[maxn],son[maxn];
vector<int> v[maxn];
priority_queue<int,vector<int>,greater<int> > q;

int main() {
int n,i,sum,j,min;
//	n=1;
//	while (scanf("%d",&a
)!=EOF) n++;
scanf("%d",&n);
for (i=1;i<n;i++) scanf("%d",&a[i]);
mem(son);
for (i=1;i<n;i++) {
son[a[i]]++;
}
for (i=1;i<=n;i++) {
if (!son[i]) q.push(i);
}
for (i=1;i<n;i++) {
int now=q.top();
v[a[i]].push_back(now);
v[now].push_back(a[i]);
q.pop();
son[a[i]]--;
if (!son[a[i]]) q.push(a[i]);
}
for (i=1;i<=n;i++) {
sort(v[i].begin(),v[i].end());
int size=v[i].size();
printf("%d:",i);
for (j=0;j<size;j++) {
printf(" %d",v[i][j]);
}
printf("\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: