POJ 2367 系统树
And in the Planetary Council the confusing genealogical system leads to some embarrassment. There meet the worthiest of Martians, and therefore in order to offend nobody in all of the discussions it is used first to give the floor to the old Martians, than to the younger ones and only than to the most young childless assessors. However, the maintenance of this order really is not a trivial task. Not always Martian knows all of his parents (and there's nothing to tell about his grandparents!). But if by a mistake first speak a grandson and only than his young appearing great-grandfather, this is a real scandal.
Your task is to write a program, which would define once and for all, an order that would guarantee that every member of the Council takes the floor earlier than each of his descendants.
5 0 4 5 1 0 1 0 5 3 0 3 0Sample Output
2 4 5 3 1
火星人的血缘关系体系已经够混乱的了。事实上,火星人在他们想要的时间和地点发芽。他们以不同的群体聚集在一起,这样火星人可以有一个父母和十个父母。一百个孩子不会让任何人感到惊讶。
火星人已经习惯了这一点,他们的生活方式对他们来说似乎很自然。 在行星理事会,混乱的系谱系统导致了一些尴尬。在那里遇到最有价值的火星人,因此为了在所有的讨论中不冒犯任何人,它首
先被用来让老火星人发言,而不是让年轻的火星人发言,也只是让最年轻的没有孩子的评估者发言。然而,维持这一秩序确实不是一项微不足道的任务。火星人并不总是认识他所有的父母(关于他的
祖父母也没什么好说的!)。但是如果由于一个错误先说一个孙子,而只是比他年轻时显得曾祖父,这是一个真正的丑闻。 你的任务是编写一个程序,一劳永逸地确定一个秩序,保证安理会的每个成
员比他的每一个后代发言更早。
投入 标准输入的第一行只包含一个数字N,1 < = N < = 100——火星行星理事会的一些成员。根据几个世纪以来的传统,委员会的成员用从1到N的自然数来计数。此外,正好有N条线,而且,第I条线
包含第I个成员的孩子的列表。子列表是以任意顺序由空格分隔的一系列子序列号。孩子列表可能为空。列表(即使是空的)以0结尾。
输出 标准输出应该在其唯一的一行中包含一系列由空格分隔的扬声器号码。如果几个序列满足问题的条件,您将把它们中的任何一个写入标准输出。至少有一个这样的序列总是存在的。
样本值输入 5 0 4 5 1 0 1 0 5 3 0 3 0
抽样输出 2 4 5 3 1
#include<stdio.h>
#include<iostream>
using namespace std;
int num_edge=0,head[10001],ht[10001],que[10001],hed,tail;
struct Edge
{
int to,next;
}edge[100001];
void add_edge(int from,int to)
{
edge[++num_edge].next=head[from];
edge[num_edge].to=to;
head[from]=num_edge;
}
int main()
{
int a,n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
while(1)
{
scanf("%d",&a);
if(a==0) break;
else {add_edge(i,a);ht[a]++; //ht数组记录入度;
}
}
}
hed=0;tail=0;
for(int i=1;i<=n;i++)
{
if(ht[i]==0)
{
tail++;que[tail]=i; //入度为零加入队列
}
}
while(hed<tail)
{
hed++;
for(int i=head[que[hed]];i!=0;i=edge[i].next)
{ ht[edge[i].to]--; //队首出队后接下来的点的入度就减少一
if(ht[edge[i].to]==0)
{tail++;que[tail]=edge[i].to;//入度为零入队
}
}
}
for(int i=1;i<=n;i++) printf("%d ",que[i]);
return 0;
}
拓扑排序例题
所谓一张有向无环图(DAG)的拓扑序列,即为一个点的序列,满足对任意一条边(u,v),u都出现在v的前面。
求解拓扑序列的方法叫做『拓扑排序』。
求法:首先,辈分最高的人肯定入度为0。
找出图中所有入度为0的点,放入一个队列中。(顺序无所谓)
用类似BFS的方法,我们依次从队首取出点来,先输出到最后的答案序列,然后遍历从当前点u发出的所有边(u, v)。对v入度减一。如果某个v的入度减为0了,这个v就变成了目前辈分最高的状态,将其由队尾插入。