WUST 1949 家谱树(拓扑排序+dfs)

港控/mmm° 2022-06-12 04:22 241阅读 0赞

1949: 家谱树

Time Limit: 1 Sec Memory Limit: 128 MB 64bit IO Format: %lld
Submitted: 7 Accepted: 5
[ Submit][ Status][ Web Board]

Description

有个人的家族很大,辈分关系很混乱,请你帮整理一下这种关系。

给出每个人的孩子的信息。

输出一个序列,使得每个人的后辈都比那个人后列出。

Input

多组测试数据。

第1行一个整数N(1<=N<=100),表示家族的人数。

接下来N行,第I行描述第I个人的儿子。

每行最后是0表示描述完毕。

Output

输出一个序列,使得每个人的后辈都比那个人后列出。

如果有多解,输出时序号越小的越在前。

" class="reference-link">Sample Input copy.gif

  1. 5
  2. 0
  3. 4 5 1 0
  4. 1 0
  5. 5 3 0
  6. 3 0
  7. 12
  8. 2 3 4 12 0
  9. 3 0
  10. 5 7 8 0
  11. 5 0
  12. 7 0
  13. 8 0
  14. 0
  15. 0
  16. 10 11 12 0
  17. 12 0
  18. 6 0
  19. 0

Sample Output

  1. 2 4 5 3 1
  2. 1 2 3 4 5 7 9 10 11 6 8 12

[ Submit][ Status][ Web Board]

题解:

这题真是醉了,那么简单的一题学了我半天,原因是网上的题解都是输出任意一个解就行,我们学校居然要输出序号最小的解。。。不过还是好好学了拓扑排序的,所谓拓扑排序,就是给你一堆数据,给你这些数据的类似于大小关系的二元关系(不形成环),让你给他们按关系从大到小(或者从小到大)进行排序,思路就是找一个出度为0的点,然后把它输出来,并把与他有关系的关系都去掉(去掉一些数据的出度),寻找下一个出度为0的点。。循环就找完了。。而这题是一个极品,不能用常规方法做,我就直接dfs了。。

代码:

  1. #include<algorithm>
  2. #include<iostream>
  3. #include<cstring>
  4. #include<stdio.h>
  5. #include<math.h>
  6. #include<string>
  7. #include<stdio.h>
  8. #include<queue>
  9. #include<stack>
  10. #include<map>
  11. #include<deque>
  12. using namespace std;
  13. int vis[105];//存该点有没有被输出过
  14. int a[105][105];//存每一个点的儿子
  15. int num[105],n,tag;//num计算每一个点的儿子数目
  16. void dfs(int ans)//ans记入输出了几个点
  17. {
  18. if(ans>=n||tag)//只要找到一个就全停
  19. {
  20. tag=1;
  21. return;
  22. }
  23. int i,j;
  24. int p[105];
  25. memset(p,0,sizeof(p));//初始化为0,如果还没输出的点中出现了这个点是他的儿子则这个点不能用
  26. for(i=1;i<=n;i++)
  27. {
  28. if(!vis[i])
  29. {
  30. for(j=0;j<num[i];j++)//对每一个点的儿子进行遍历覆盖
  31. {
  32. p[a[i][j]]=1;
  33. }
  34. }
  35. }
  36. for(i=1;i<=n;i++)
  37. {
  38. if(!p[i]&&!vis[i])//找到一个没有输出的点里面没人是他的爸爸就输出,hhhh这句话有点好笑
  39. {
  40. if(ans==0)
  41. {
  42. printf("%d",i);
  43. }
  44. else
  45. printf(" %d",i);
  46. vis[i]=1;//输出过了
  47. break;
  48. }
  49. }
  50. dfs(ans+1);//很好,下一个
  51. }
  52. int main()
  53. {
  54. int x,i,j,tot,sum;
  55. while(scanf("%d",&n)!=EOF)
  56. {
  57. tag=0;
  58. memset(vis,0,sizeof(vis));
  59. memset(num,0,sizeof(num));
  60. for(i=1;i<=n;i++)
  61. {
  62. while(scanf("%d",&x)&&x)
  63. {
  64. a[i][num[i]]=x;
  65. num[i]++;
  66. }
  67. }
  68. dfs(0);
  69. printf("\n");
  70. }
  71. }

发表评论

表情:
评论列表 (有 0 条评论,241人围观)

还没有评论,来说两句吧...

相关阅读

    相关 拓扑排序

     一个较大的工程往往被划分成许多子工程,我们把这些子工程称作活动(activity)。在整个工程中,有些子工程(活动)必须在其它有关子工程完成之后才能开始,也就是说,一个子工程