其中 dfs 的代碼 主要來自: https://blog.csdn.net/Jaster_wisdom/article/details/51067234算法
一,前言dom
這裏講的都是無向圖,沒講有向的。ide
其中,若是 無向圖沒有奇數度結點,則具備歐拉回路,是歐拉圖測試
若是 無向圖有兩個奇數度結點,則僅有歐拉通路,是半歐拉圖spa
此外,則該無向圖既不是歐拉圖也不是半歐拉圖.net
測試數據的圖:code
二,Fleury 算法blog
1, 算法思想get
選取起點,其中歐拉圖的起點任意,半歐拉圖的起點從 兩個奇度結點中的任意一個 開始。string
而後從起點依次選邊,每選一條邊就從圖中刪去。選取條件是:① 與上一條已選取的邊關聯;② 除非無別的邊可 選,不然不能選割邊(橋)。
2,步驟
① 判斷該圖是什麼圖
② 選擇起點
③ 刪邊
④ 將刪除的邊 加入 歐拉路中
⑤ 循環 ③ ④,直至 無邊 可刪
3,代碼
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #include<string.h> #define N 1000 int a[N][N]; //鄰接矩陣 int n, m; // n 點數 , m 邊數 int judge_bridge(int i) // 經過判斷以 i 爲終點的邊 是否 只有一個,來判斷這條邊是不是 割邊 { int cnt = 0; for (int j = 0; j < n; j++) { if (a[i][j]) cnt++; } if (cnt == 1) return 0; return 1; } void Fleury(int cur) // cur 爲起點 { int t = 0; // 記錄割邊的終點 int f3 = 0; // 標記 第一條邊 while (1) { int f1 = 0; // 標記 是否有找到 正常邊 int f2 = 0; // 若是有 割邊,記錄 第一條割邊 for (int j = 0; j < n; j++) { if (a[cur][j]) { if (judge_bridge(j)) // 若是這條邊不是割邊,則刪除這條邊 { f1 = 1; a[cur][j] = 0; a[j][cur] = 0; printf(f3 == 0 ? "(%d,%d)" : "->(%d,%d)", cur, j); f3 = 1; cur = j; break; } if (judge_bridge(j) == 0 && f2 == 0) // 記錄可能出現的割邊,以備不時之需 { f2++; t = j; } } } if (f1 == 0 && f2 == 1) // 到了不選割邊不行的地步了 { a[cur][t] = 0; a[t][cur] = 0; printf(f3 == 0 ? "(%d,%d)" : "->(%d,%d)", cur, t); f3 = 1; cur = t; } if (f1 == 0 && f2 == 0) // 無邊可選,鄰接矩陣空了,算法結束 { puts(""); break; } } } void creat() // 直接 輸入鄰接矩陣 { for (int i = 0; i < n; i++)//使用鄰接矩陣表示圖 { for (int j = 0; j < n; j++) { scanf("%d", &a[i][j]); } } } void judge() { int odd = 0; // 存奇數度數 的個數 int flag = 0; // 存 奇度邊 的編號,若是是 半歐拉圖 就從 奇度邊 出發,如果 歐拉回路,就隨便從 0 開始 for (int i = 0; i < n; i++) { int cnt = 0; for (int j = 0; j < n; j++) // 統計每一個結點的 度數 cnt += a[i][j]; if (cnt % 2) // 若爲 奇數,總數 +1 { flag = i; odd++; } } if (odd == 0) { printf("斷定:該無向圖沒有奇數度結點,具備歐拉回路,是歐拉圖\n"); printf("歐拉回路爲:"); Fleury(flag); } else if (odd == 2) { printf("斷定:該無向圖有兩個奇數度結點,僅有歐拉通路,是半歐拉圖\n"); printf("歐拉通路爲:"); Fleury(flag); } else printf("斷定:該無向圖既不是歐拉圖也不是半歐拉圖\n"); } int main(void) { while (scanf("%d", &n) != EOF) // 輸入結點數 嘗試了一下就 234 會有 歐拉路 { memset(a, 0, sizeof(a)); creat(); // 直接 輸入鄰接矩陣 judge(); // 判斷 該 鄰接矩陣 是什麼圖,如有歐拉路 則輸出 路徑 } system("pause"); return 0; } /* 測試數據1:歐拉回路 7 0 1 0 0 1 0 0 1 0 1 1 1 0 0 0 1 0 1 0 0 0 0 1 1 0 1 0 1 1 1 0 1 0 1 0 0 0 0 0 1 0 1 0 0 0 1 0 1 0 測試數據2:歐拉通路 5 0 1 1 0 0 1 0 1 1 1 1 1 0 1 1 0 1 1 0 1 0 1 1 1 0 */
三,DFS
1,我的感受,不知對錯
① 這裏面雖然沒有判斷割邊,可是判斷了孤立點,它用深搜進行刪邊,這裏的深搜只進行搜索刪邊,並無回溯。
可是它將結點壓入棧中了,而後再經過 棧中的結點 進行回溯,將孤立點加入通路中。那沒什麼存下來的路徑不是散亂的點呢?
② 咱們要明白一個前提就是這是個 歐拉圖 或者是 半歐拉圖,若是是從起點開始搜索的話,是有可能一次搜完的。
那何時會出現幾條路徑呢,只有它在有其餘的路可選的狀況下,搜索了割邊。
③ 我猜想若是搜索的是割邊的話,那麼剩餘圖必定是迴路(由於畫了好幾回都是這樣,也不會證實,不知道對不對 ┌(; ̄◇ ̄)┘)
因此在咱們經過 棧 裏面的 結點 進行回溯時,在中間對剩餘圖進行再次深搜,就至關於在原通路中插入一條迴路,仍然仍是一條通路。
這樣才能存下來的路徑不是散亂的點
2,代碼
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #include<string.h> #include<stack> using namespace std; #define N 1000 int map[N][N], way[N]; stack<int>s; int n, m; // 點數 邊數 void dfs(int k) { s.push(k); for (int i = 0; i < n; i++) // 一條路 刪到沒路 無論有無割邊 { if (map[k][i]) { map[i][k] = map[k][i] = 0; dfs(i); break; } } } void Fleury(int k) { stack<int>ss; s = ss; // 棧的清空 int cnt = 0; s.push(k); // 起點入棧 while (s.size()) { int vertex = s.top(); s.pop(); int flag = 0; for (int i = 0; i < n; i++) // 經過判斷 與vertx 相鄰的邊的個數 來判斷是否 這點是否 是孤立點 { if (map[vertex][i] > 0) // 只要有邊 就能夠刪 { flag = 1; break; } } if (flag == 0) // 該點是 孤立點 way[cnt++] = vertex; else // 不是孤立點 能夠繼續 刪邊 dfs(vertex); } for (int i = cnt - 1; i > 0; i--) // 打印路徑 printf("%d->", way[i]); printf("%d\n", way[0]); } void judge() { int odd = 0; // 存奇數度數 的個數 int flag = 0; // 存 奇度邊 的編號,若是是 半歐拉圖 就從 奇度邊 出發,如果 歐拉回路,就隨便從 0 開始 for (int i = 0; i < n; i++) { int cnt = 0; for (int j = 0; j < n; j++) // 統計每一個結點的 度數 cnt += map[i][j]; if (cnt % 2) // 若爲 奇數,總數 +1 { flag = i; odd++; } } if (odd == 0) { printf("斷定:該無向圖沒有奇數度結點,具備歐拉回路,是歐拉圖\n"); printf("歐拉回路爲:"); Fleury(flag); } else if (odd == 2) { printf("斷定:該無向圖有兩個奇數度結點,僅有歐拉通路,是半歐拉圖\n"); printf("歐拉通路爲:"); Fleury(flag); } else printf("斷定:該無向圖既不是歐拉圖也不是半歐拉圖\n"); } int main(void) { scanf("%d%d", &n, &m); for (int i = 0; i < m; i++) { int x, y; scanf("%d%d", &x, &y); map[x][y] = map[y][x] = 1; } judge(); system("pause"); return 0; } /* 測試數據1:歐拉回路 7 10 0 1 0 4 1 2 1 4 1 3 2 3 3 4 4 5 5 6 6 3 測試數據2:歐拉通路 5 8 0 1 0 2 1 2 1 3 1 4 2 3 2 4 3 4 */
=========== ========= ======== ======= ====== ===== ==== === == =
哪裏會有人喜歡孤獨,只是不喜歡失望罷了。
—— 村上春樹