1、拓扑排序的介绍
对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前。
拓扑排序对应施工的流程图具有特别重要的作用,它可以决定哪些子工程必须要先执行,哪些子工程要在某些工程执行后才可以执行。为了形象地反映出整个工程中各个子工程(活动)之间的先后关系,可用一个有向图来表示,图中的顶点代表活动(子工程),图中的有向边代表活动的先后关系,即有向边的起点的活动是终点活动的前序活动,只有当起点活动完成之后,其终点活动才能进行。通常,我们把这种顶点表示活动、边表示活动间先后关系的有向图称做顶点活动网(Activity On Vertex network),简称AOV网。
一个AOV网应该是一个有向无环图,即不应该带有回路,因为若带有回路,则回路上的所有活动都无法进行(对于数据流来说就是死循环)。在AOV网中,若不存在回路,则所有活动可排列成一个线性序列,使得每个活动的所有前驱活动都排在该活动的前面,我们把此序列叫做拓扑序列(Topological order),由AOV网构造拓扑序列的过程叫做拓扑排序(Topological sort)。AOV网的拓扑序列不是唯一的,满足上述定义的任一线性序列都称作它的拓扑序列。
2、拓扑排序的实现步骤
- 在有向图中选一个没有前驱的顶点并且输出
- 从图中删除该顶点和所有以它为尾的弧(白话就是:删除所有和它有关的边)
- 重复上述两步,直至所有顶点输出,或者当前图中不存在无前驱的顶点为止,后者代表我们的有向图是有环的,因此,也可以通过拓扑排序来判断一个图是否有环。
关于代码,我有一点,就是第二层for循环里的break,一旦找到一个入度为0的点立刻跳出本次循环,因为,外围的for循环个数为n,第二层for循环如果多删一个(删除个数大于一)那么就会导致最后节点删完还在for循环。
下面是这个题
数据结构实验之图论十:判断给定图是否存在合法拓扑序列
Time Limit: 1000 ms
Memory Limit: 65536 KiB
Problem Description
给定一个有向图,判断该有向图是否存在一个合法的拓扑序列。
Input
输入包含多组,每组格式如下。
第一行包含两个整数n,m,分别代表该有向图的顶点数和边数。(n<=10)
后面m行每行两个整数a b,表示从a到b有一条有向边。
Output
若给定有向图存在合法拓扑序列,则输出YES;否则输出NO。
Sample Input
1 0 2 2 1 2 2 1
Sample Output
YES NO
#include <iostream> #include <bits/stdc++.h> using namespace std; int main() { int n,m,i,j,k,flag,a,b; while(scanf("%d %d",&n,&m)!=EOF) { int mapp[12][12]={{0,0}}; int du[12]={0}; int vis[12]={0}; for(i=1;i<=m;i++) { scanf("%d %d",&a,&b); mapp[a][b]=1; du[b]++; } for(i=1;i<=n;i++) { flag=0; for(j=1;j<=n;j++) { if(vis[j]==0&&du[j]==0) { flag=1; for(k=1;k<=n;k++) { if(mapp[j][k]) du[k]--; } vis[j]=1; break; } } if(flag==0) { break; } } if(flag) { printf("YES\n"); } else { printf("NO\n"); } } return 0; }