#图# #拓扑排序# ----- 家谱树

拓扑排序

         对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前。

 

        1. 有向无环图

          在图论中,如果一个有向图无法从某个顶点出发经过若干条边回到该点,即不应该带有回路,则这个图是一个有向无环图(DAG图)。
          因为有向图中一个点经过两种路线到达另一个点未必形成环,因此有向无环图未必能转化成树,但任何有向树均为有向无环图。
                         
          性质:有向无环图的生成树个数等于入度非零的节点的入度积。
 

       2. 拓扑序列

          在AOV网中(一个AOV网应该是一个有向无环图,即不应该带有回路。),若不存在回路,则所有活动可排列成一个线性序列,使得每个活动的所有前驱活动都排在该活动的前面,我             们把此序列叫做拓扑序列(Topological order),由AOV网构造拓扑序列的过程叫做拓扑排序(Topological sort)。AOV网的拓扑序列不是唯一的,满足上述定义的任一线性序列都称作           它的拓扑序列。
 
        3.拓扑排序
           由AOV网构造拓扑序列的拓扑排序算法主要是循环执行以下两步,直到不存在入度为0的顶点为止。
             (1) 选择一个入度为0的顶点并输出之;
             (2) 从网中删除此顶点及所有出边。
           循环结束后,若输出的顶点数小于网中的顶点数,则输出“有回路”信息,否则输出的顶点序列就是一种拓扑序列。
 
 
家谱树
 

【题目描述】
有个人的家族很大,辈分关系很混乱,请你帮整理一下这种关系。
给出每个人的孩子的信息。
输入一个序列,使得每个人的后辈都比那个人后列出。
【输入】
第一行一个整数(1<=N<=100),表示家族的人数。
接下来N行,第I行表示第I个人的儿子。
每行最后是0表示描述完毕。
【输出】
输出一个序列,使得每个人的后辈都比那个人后列出。
如果有多解输出任意一解。
【输入样例】
5
0
4 5 1 0
1 0
5 3
0
3 0
【输出样例】
2 4 5 3 1

 

 1 #include<stdio.h>
 2 
 3 int n;
 4 int m,cnt; 
 5 int r[105],c[105],a[105][105];
 6 int ans[105];
 7 
 8 int main(){
 9     scanf("%d",&n);
10     for(int i=1;i<=n;i++){
11         int x;
12         scanf("%d",&x);
13         while(x!=0){
14             c[i]++;// 第i个出度++ 
15             a[i][c[i]]=x;//第i个人第c【i】个出度是x 
16             r[x]++;//x入度++ 
17             scanf("%d",&x);
18         }
19     }
20     
21     for(int i=1;i<=n;i++)
22        if(r[i]==0)ans[++cnt]=i;//找入度为0的点的个数  
23      
24     int x; 
25     while(m!=n){
26          x=ans[cnt];//第一个入读为0 
27          printf("%d ",x);
28          cnt--;//入度为0点个数-- 
29          m++;//已输出人数++ 
30          for(int i=1;i<=c[x];i++){
31              r[a[x][i]]--;//入度为0点和他相连所有边终点入度-- 
32              if(r[a[x][i]]==0)ans[++cnt]=a[x][i];//如果点入度==0,进队 
33          }
34     }
35    return 0;
36 }

 

posted @ 2016-11-04 10:45  WJ-Ting  阅读(787)  评论(0编辑  收藏  举报