拓扑排序
1.定义
在图论中,拓扑排序(Topological Sorting)是一个有向无环图(DAG, Directed Acyclic Graph)的所有顶点的线性序列。且该序列必须满足下面两个条件:
1.每个顶点出现且只出现一次。
2.若存在一条从顶点 A 到顶点 B 的路径,那么在序列中顶点 A 出现在顶点 B 的前面。
2.应用
在整个工程中,有些子工程(活动)必须在其它有关子工程完成之后才能开始,为了形象地反映出整个工程中各个子工程(活动)之间的先后关系,可用一个有向图来表示,图中的顶点代表活动(子工程),图中的有向边代表活动的先后关系,即有向边的起点的活动是终点活动的前序活动,只有当起点活动完成之后,其终点活动才能进行。通常,我们把图称做顶点活动网(Activity On Vertex network),简称AOV网。
一个AOV网应该是一个有向无环图,即不应该带有回路,因为若带有回路,则回路上的所有活动都无法进行
3.实现
4.训练
(附上某大佬的博客: https://dylanli-hang.github.io/2019/07/26/拓扑排序/ )
最基础的模板:
UVA10305 给任务排序 Ordering Tasks
https://www.luogu.org/problem/UVA10305
没有账号的同学去: https://vjudge.net/problem/UVA-10305 提交需要处理一点的拓扑排序:
P1038神经网络
https://www.luogu.org/problem/P1038拓扑排序保证无后效性+简单动规:
P1137 旅行计划
https://www.luogu.org/problem/P1137可以用拓扑排序解决的:
P1983 车站分级
https://www.luogu.org/problem/P1983
模板题 相当直接的做法:
#include<cstdio> #include<cstring> #include<iostream> #define sizen 120 using namespace std; int n,m; int map[sizen][sizen],degree[sizen]; bool vis[sizen]; //若遇到入度为0的点,删除所有以该点为起点的边 void dfs(int i){ for(int j=1;j<=n;j++) if(map[i][j]){ map[i][j] = 0; degree[j]--; if(degree[j] == 0)printf("%d ",j),vis[j] = 1,dfs(j); } return; } int main(){ int u,v; while(cin>>n>>m){ if(m == 0 && n == 0)break; memset(map,0,sizeof(map)); memset(degree,0,sizeof(degree)); memset(vis,0,sizeof(vis)); for(int i=1;i<=m;i++){ scanf("%d%d",&u,&v); map[u][v] = 1; } for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++) if(map[i][j])degree[j]++; } for(int i=1;i<=n;i++) if(degree[i] == 0 && !vis[i]){ printf("%d ",i); vis[i] = 1; dfs(i); } printf("\n"); } return 0; }