1. 程式人生 > >深度優先遍歷找出一個無向圖中的環

深度優先遍歷找出一個無向圖中的環

進行深度優先遍歷的時候,當考察的點的下一個鄰接點是已經被遍歷的點,並且不是自己之前的父親節點的時候,我們就找到了一條逆向邊,因此可以判斷該無向圖中存在環路。

visited陣列記錄了節點的訪問狀態,visited[i] = 0表示節點i尚未被訪問過; visited[i] = 1表示節點i被訪問了,但是尚未被檢測完畢; visited[i] = 2表示節點i已經被檢測完畢了,對於檢測完畢了的節點,其所有的臨邊都已經被考慮過了,如果存在逆向邊的話已經被檢測了,從而避免了重複地進行檢測。 father[i]表示到達節點i經過的前驅節點,通過反向索引father陣列,我們可以找出這個環。

#include <stdio.h>
#include <stdlib.h> int * newIntRaw(int n) { return (int *)malloc(sizeof(int) * n); } int * newInt(int n, int init) { int *p = newIntRaw(n); int i; for (i = 0; i < n; ++i) p[i] = init; return p; } int ** newMap(int n, int m, int init) { int **res = (int **)malloc
(sizeof(int *) * n); int i; for (i = 0; i < n; ++i) res[i] = newInt(m, init); return res; } typedef struct { int e; int n; int **map; } Graph; Graph * newGraph() { int n, e; int i; int from, to; Graph *g = (Graph *)malloc(sizeof(Graph)); scanf
("%d %d", &n, &e); g->n = n; g->e = e; g->map = newMap(n, n, 0); for (i = 0; i < e; ++i) { scanf("%d %d", &from, &to); g->map[from][to] = 1; g->map[to][from] = 1; } return g; } void dispGraph(Graph *g) { int i, j; for (i = 0; i < g->n; ++i) { printf("%d: ", i); for (j = 0; j < g->n; ++j) { if (g->map[i][j] == 1) printf("%d ", j); } printf("\n"); } } // ---------------------------solve----------------------- int *visited; int *father; void dfs(Graph *g, int s) { int i; visited[s] = 1; for (i = 0; i < g->n; ++i) { if (g->map[s][i] == 1) { if (visited[i] == 0) { father[i] = s; dfs(g, i); } else if (visited[i] == 1 && i != father[s]) { int tmp = s; printf("find a ring: %d --> ", i); while (tmp != i) { printf("%d --> ", tmp); tmp = father[tmp]; } printf("%d\n", tmp); } } } visited[s] = 2; // 避免重複計算環 } void findRing(Graph *g) { // dispGraph(g); int i; visited = newInt(g->n, 0); father = newInt(g->n, -1); for (i = 0; i < g->n; ++i) if (visited[i] == 0) dfs(g, i); } int main() { Graph *g = newGraph(); findRing(g); return 0; } /* 5 6 0 1 0 4 4 3 3 1 1 2 3 2 */