1.自然语言描述
有向无环图(DAG图)能够转化为一个序列,该序列的性质是对于每条边(x,y),x在序列中出现在y之前;该序列被称为拓扑序列。由拓扑序列性质可知一个DAG图的拓扑序列并不是唯一的。计算拓扑序列的方法是:每次去除入度为0的点并去掉其邻接边(即将其邻接点的入度减1)记录其每次去除顺序,直至所有点都被处理。若发现不能得到拓扑序列,则说明该图一定不是DAG图;也就是说,不含环的有向图一定存在拓扑序列。
2.代码描述
题目:Acwing.848 有向图的拓扑序列题目链接
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int MAXN=1e5+10;
int n,m,h[MAXN],e[2*MAXN],ne[2*MAXN],d[MAXN],tra[MAXN],idx,cnt;
//d用来记录每个结点的入度
//tra记录拓扑序列,cnt表示拓扑序列长度
void add(int a,int b)
{
e[idx]=b;
ne[idx]=h[a];
h[a]=idx++;
}
bool topsort()
{
queue<int> q;
for(int i=1;i<=n;i++)//从入度为0的结点开始遍历
if(!d[i]){
q.push(i);
tra[cnt++]=i;
}
while(!q.empty()){
auto t=q.front();
q.pop();
for(int i=h[t];i!=-1;i=ne[i]){
int j=e[i];
d[j]--;
if(!d[j]){
q.push(j);
tra[cnt++]=j;
}
}
}
return d[n]==0;//如果存在拓扑序列,最后一个点也会被去掉所有的入边
}
int main(void)
{
cin>>n>>m;
memset(h,-1,sizeof(h));
for(int i=0;i<m;i++){
int a,b;
cin>>a>>b;
add(a,b);
d[b]++;
}
if(topsort()){
for(int i=0;i<cnt;i++)
cout<<tra[i]<<' ';
cout<<endl;
}else
cout<<-1<<endl;
return 0;
}