引入
- 一个工程有许多子工程,称为活动,在有向图中用顶点表示活动,有向边表示活动的先后顺序,这样的图称为AOV网,在AOV网中为了更好的完成工程,需要满序先后关系,将各活动排一个先后次序,就称为拓扑排序
问题
解决方法
- 从有向图中选一个没有前驱的结点,输出
- 从图中删除这个点以及所有出边
- 重复上述两步直至图为空,或者无法删除
- 注意,拓扑排序存在多解,可能同时存在两个没有前驱的结点
实现
- 开一个队列,把入度为0的点弹入,弹出队首,给邻接点入读减一,如果减成0,入队
- 对于每个点每个边都访问一次,O(nm)
#include<bits/stdc++.h>
using namespace std;
typedef struct{
int t,nxt;
}E;
E edge[101010];
int head[1010];
int cnt=0;
int n,m;
void insert(int st,int to){
edge[++cnt].t=to;
edge[cnt].nxt=head[st];
head[st]=cnt;
}
int ans[1010];
int inc[1010];
queue<int> q;
void tuopo(){
for(int i=1;i<=n;i++){
if(inc[i]==0) q.push(i);
}
int tot=0;
while(!q.empty()){
int x=q.front();
ans[tot]=x;
// cout << x << ' ' ;
q.pop();
tot++;
for(int i=head[x];i!=-1;i=edge[i].nxt){
inc[edge[i].t]--;
if(inc[edge[i].t]==0) q.push(edge[i].t);
}
}
if(tot!=n) cout << -1 ;
else{
for(int i=0;i<n;i++)
cout << ans[i] << ' ';
}
cout << endl;
}
int main(){
cin >> n >> m;
memset(head,-1,sizeof(head));
for(int i=1;i<=m;i++){
int a,b;
cin >> a >> b;
inc[b]++;
insert(a,b);
}
tuopo();
return 0;
}
应用