zoukankan      html  css  js  c++  java
  • #图# #拓扑排序# ----- 家谱树

    拓扑排序

             对一个有向无环图(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 }
  • 相关阅读:
    「搬运」影魔
    「不会」斯特林数
    「不会」二项式反演
    「不会」插头dp
    「不会」主定理
    「不会」网络流
    接口和抽象类的区别
    TestNG常用注解
    九九乘法表-Java
    冒泡排序和选择排序--Java
  • 原文地址:https://www.cnblogs.com/wjting/p/6029388.html
Copyright © 2011-2022 走看看