这里要引入两个概念:
1.树边:是一条未被遍历过的边,它指向一个未被访问过的点。
2.反向边:是一条未被遍历过的边,它指向一个被访问过的点。
如果图中有环路的存在,那么环路的最后一个边必然是一条反向边。
那么,我们在DFS遍历的过程当中,只需要添加一条语句来判断所有未被检查过的边的指向点是否已被访问过,就可以判断出这个图是否存在环路了。
#include <stdio.h>
#include <string.h>const int maxv = 1000;
const int maxe = 5000;
const int maxn = 1000;
/*
* 邻接矩阵
*
*/
struct adjMetrix {int G[maxn+10][maxn+10];int visit[maxn];int n;void addedge(int u, int v) {G[u][v] = 1;return ;}void read() {memset(G, 0, sizeof(G));memset(visit, 0, sizeof(visit));int u, v, w;scanf("%d", &n);for (int i=0; i<n; i++) {scanf("%d %d", &u, &v);addedge(u, v);}return ;}void dfs(int i) {for (int j=0; j<=n; j++) {if (G[i][j]!=0 && visit[j]==0) {printf("%d %d\n", i, j);visit[j] = 1;dfs(j);}}}
};/*
* 邻接链表
*
*/
struct Edge {int to, w, next;
};struct adjTable {int node[maxv];int visit[maxe];int cnt;bool cycle;struct Edge e[maxe];void init() {memset(node, -1, sizeof(node));memset(visit, 0, sizeof(visit));cnt = 0;cycle = false;}void addedge(int u,int v) {e[cnt].to = v;e[cnt].next = node[u];node[u] = cnt++;}void read() {int n, u, v, w;scanf("%d", &n);for (int i=1; i<=n; i++) {scanf("%d %d", &u, &v);addedge(u, v);}return ;}void dfs(int p) {int i;for (i=node[p]; i!=-1; i=e[i].next) {if ( visit[e[i].to] )cycle = true;if (visit[ e[i].to ] == 0) {printf("%d %d\n", p, e[i].to);visit[ p ] = 1;dfs( e[i].to );}}}
};struct adjTable table;int main() {freopen("in.txt", "r", stdin);table.init();table.read();table.dfs(1);if (table.cycle)printf("有环!\n");elseprintf("无环!\n");return 0;
}