【9010】家谱树

Time Limit: 1 second
Memory Limit: 128 MB

【问题描述】

有个人的家族很大,辈分关系很混乱,请你帮真理一下这种关系。 给出每个人的孩子的信息。 输出一个序列,使得每个人的后备都比那个人后列出。 

【输入格式】

第一行一个整数n(1<=n<=100),表示家族的人数。 接下来n行,第i行描述第i个的儿子。 每行最后是0表示描述完毕。

【输出格式】

输出一个序列,使得每个人的后辈都比那个人后列出。 如果有多解输出任意一解。

Sample Input

5
0
4 5 1 0
1 0
5 3 0
3 0

Sample Output

2 4 5 3 1


【题解】

这是道拓扑排序的题。
首先。对于第i行出现的整数。
他们都是i的后代。
于是给这些整数和i之间建立一条有向边。由这些整数指向i。这些整数的出度递增。
然后,要记录这些整数和i之间有边。方便后续递减与已经输出的点相关的点的出度。
每次找出度为0的点输出即可。

【代码】

#include <cstdio>
#include <cstring>

int n,w[101][101],chu[101],ans[101],num = 0;

void input_data()
{
	memset(w,0,sizeof(w)); //记录和弹出的点相关的点的信息。 
	scanf("%d",&n);
	for (int i = 1;i <= n;i++)
		{
			int x;
			scanf("%d",&x); //输入x  
			while (x != 0) //如果不为0 就继续输入 
				{
					w[i][x] = 1; //记录i和x有联系 
					chu[x] ++; //x->i的一条单向边 
					scanf("%d",&x);	 //继续输入 
				}
		}
}

void get_ans()
{
	for (int i = 1;i <= n;i++) //肯定要输出n个数字的 
		{
			for (int j = 1;j <= n;j++) //找到出度为0 的点 
				if (chu[j] == 0)
					{
						ans[++num] = j; //把它加入答案。 
						chu[j] = -1; //同时把这个出度置为-1,下次就不会再找到这个点了. 
						for (int k = 1;k <= n;k++) //找到和这个点有关的点 
							if (w[j][k] == 1) //如果相连着去掉这条边同时和这个点有关的点的出度递减。 
								{
									w[j][k] = 0;
									chu[k]--;	
								}
					}
		}
}

void output_ans()
{
	for (int i = 1;i <= num-1;i++)
		printf("%d ",ans[i]);
	printf("%d\n",ans[num]);	
}

int main()
{
	//freopen("F:\\rush.txt","r",stdin);
	input_data();
	get_ans();
	output_ans();
	return 0;	
}


posted @ 2017-10-06 19:23  AWCXV  阅读(166)  评论(0编辑  收藏  举报