拓扑排序

拓扑排序的过程大概是这样的:
① 选择一个入度为0 的结点并直接输出。
② 删除这个结点以及与它关联的所有边。
③ 重复步骤①和②,直到找不到入度为0 的结点。

在一个有向图中,对所有的节点进行排序,要求没有一个节点指向它前面的节点。先统计所有节点的入度,对于入度为0的节点就可以分离出来,然后把这个节点指向的节点的入度减一。一直做改操作,直到所有的节点都被分离出来。如果最后不存在入度为0的节点,那就说明有环,不存在拓扑排序,也就是很多题目的无解的情况。
*1:删除1或2输出

 

 *2:删除2或3以及对应边

 

 

 *3:删除3或者4以及对应边

 

* 3:重复以上规则步骤

 

 

通过邻接矩阵来实现的代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 int ans[510][510];///邻接矩阵,记录二者是否有关联
 4 int n,indegree[510];///记录节点个数
 5 int queue[510];///保存拓扑
 6 void topsort()
 7 {
 8     int i,j,top,k=0;
 9     for(j=0; j<n; ++j)///遍历n次
10     {
11         for(i=1; i<=n; ++i)
12         {
13             if(indegree[i]==0)///找到入度为0的节点
14             {
15                 top=i;
16                 break;
17             }
18         }
19         queue[k++]=top;///当前第一名入队列,也可以直接输出
20         indegree[top]=-1;///该节点的入度更新为-1,避免重复入队列
21         for(i=1; i<=n; ++i)
22         {
23             if(ans[top][i])///删除与该店关联的边
24                 indegree[i]--;
25         }
26     }
27     for(i=0; i<k-1; ++i)
28         printf("%d ",queue[i]);
29     printf("%d\n",queue[n-1]);
30 }
31 
32 int main()
33 {
34     int i,a,b,m;
35     while(scanf("%d%d",&n,&m)!=EOF)
36     {
37         memset(indegree,0,sizeof(indegree));///数组初始化为0
38         memset(ans,0,sizeof(ans));///数组初始化为0
39         for(i=0; i<m; ++i)
40         {
41             scanf("%d%d",&a,&b);
42             if(ans[a][b]==0)
43             {
44                 ans[a][b]=1;///二者有关联
45                 indegree[b]++;///记录前驱数量
46             }
47         }
48         topsort();
49     }
50     return 0;
51 }

 

posted @ 2020-02-11 17:52  小又又  阅读(275)  评论(2编辑  收藏  举报