基于dfs的拓扑排序
以每一个入度为0
的点为起点dfs
,节点回溯时进栈(类似欧拉回路),有反向边说明有回路。
- 首先
2
节点的邻接顶点是1
和3
,由于我们是DFS
,它就会一条路走下去,所以先走左边,即到达1
号节点 - 然后
1
号节点的邻接顶点是4
,所以接下来箭头指向4
,4
是一个出度为0
的节点,它没有邻接顶点,所以不用再往下递归,把4
直接保存到栈中。 - 接着返回到
1
节点,此时1
节点没有未访问的临界点,把1
压入栈中 - 然后返回到
2
节点,接着走右边这条路,到达3
号节点,接着从3
号节点的邻接顶点出发,但是都已经访问过了,所以返回3
后,直接把3
压入栈中,最后返回2
,把2
压入栈中。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 10005;
stack<int> stk;
struct edge{
int to, nx;
}e[maxn];
int n, m, len, cycle, head[maxn], rd[maxn], vis[maxn];
void insert(int x, int y){//插边
e[++len].to = y;
e[len].nx = head[x];
head[x] = len;
}
void dfs(int u){
if(cycle) return;//已经存在环
vis[u] = -1;//标记当前点为起点
for(int i=head[u]; i; i=e[i].nx){//遍历邻接点
int v = e[i].to;
if(!vis[v]) dfs(v);
else if(vis[v] == -1){//如果回到了起点,说明存在环
printf("Cycle
");
cycle=1;
return;
}
}
vis[u] = 1;
stk.push(u);
}
int main(){
scanf("%d%d", &n, &m);
for(int i=1; i<=m; i++){
int x, y; scanf("%d%d", &x, &y);
insert(x ,y);
rd[y] ++;
}
for(int i=1; i<=n; i++) if(!rd[i]) dfs(i);//如果入度为0,开始dfs
if(!cycle)//无环
while(!stk.empty()){
printf("%d ", stk.top());
stk.pop();
}
return 0;
}