有向无环图中的拓扑排序
´有向无环图(DAG),指不存在环的有向图
´点的入度,指以这个点为结束点的边数
´点的出度,指以这个点为出发点的边数
´拓扑序就是对于节点的一个排列使得若(u,v)∈E,那么u在排列中出现的位置一定在v前面
´而拓扑排序,则是一个用于求解拓扑序的方法(只需要求出一组解)
一个合法的拓扑序(1 2 4 3 5)
´我们要如何求出其中一个拓扑序?
´我们观察到拓扑序的定义是若(u,v)∈E,那么u在排列中出现的位置一定在v前面
´也就是说,考虑一个节点u,当我们删除u在排列中的前面所有节点之后,u的入度应该为0
´因此,我们就得到了一个大致的算法思路。
´拓扑排序:
´循环n次:
´选取一个入度为0且仍存在(未出现在排列当中)的点v
´删除点v以及从点v出发的所有边,更新剩余点的入度
´选取的v的序列则是一个合法的拓扑序
#include <bits/stdc++.h> using namespace std; const int maxn=100000+15; const int maxm=100000+15; struct Edge { int x,y,next; Edge(int x=0,int y=0,int next=0):x(x),y(y),next(next){} }edge[maxm]; int sumedge,head[maxn]; int n,m; int ins(int x,int y) { edge[++sumedge]=Edge(x,y,head[x]); return head[x]=sumedge; } int h,t,line[maxn],ind[maxn]; int money[maxn]; bool boo[maxn]; int main() { scanf("%d%d",&n,&m); for (int i=1;i<=m;i++) { int u,v; scanf("%d%d",&u,&v); ins(u,v); ind[v]++; } h=1;t=0; int ss=888; for (int i=1;i<=n;i++) if (ind[i]==0) line[++t]=i,money[i]=ss; // dp[i]=max(dp[j])+1 ((j,i)) for (;h<=t;) { ss++; int now=t; for (;h<=now;h++) for (int u=head[line[h]];u;u=edge[u].next) { ind[edge[u].y]--; if (ind[edge[u].y]==0) line[++t]=edge[u].y,money[i]=ss; } } for (int i=1;i<=n;i++) printf("%d ",line[i]); printf("\n"); return 0; }