如题描述:根据给出的图输出一个可能的拓扑序列。判断能否进行拓扑排序的关键是图是否存在环。
这里我们用数组c的值表示顶点当前的状态。0代表没有被访问过,-1代表正在被访问,1代表该点及其子孙均被访问过,并且是不存在的环的点。那么我们用dfs去遍历,如果该点在被访问的过程中再次被访问,则证明存在环。或者该点没有被访问过但是在递归访问它的后继元素时存在环,也是返回失败。
看代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define INF 100000000;
using namespace std;
const int maxn = 10000 + 5;
int mp[maxn][maxn];
int c[maxn],topo[maxn],t,n;
bool dfs(int u) {
c[u] = -1;//正在访问该顶点
for(int v = 0; v < n; v++) {
if(mp[u][v])
if(c[v] < 0) return false;//绕了一圈又回来,即存在有向环,不能拓扑
else if(!c[v]&&!dfs(v)) return false;//该点的子孙存在环
}
c[u] = 1;//已经访问过该点及其子孙,并且已返回
topo[--t] = u;//存储拓扑序列,倒着存储,便于正着打印
return true;
}
bool toposort() {
t = n;
memset(c,0,sizeof(c));
for(int u = 0; u < n; u++)
if(!c[u])
if(!dfs(u))
return false;
return true;
}
int main() {
int e,x,y,t;
cin>>e>>n;
for(int i = 0; i < e; i++) {//建图
cin>>x>>y;
mp[x][y] = 1;
}
cout<<toposort()<<endl;//是否能进行拓扑排序
for(int i = 0; i < n; i++)
cout<<topo[i];//打印拓扑序列
cout<<endl;
return 0;
}