演算法專題——歐拉回路
阿新 • • 發佈:2021-10-07
歐拉回路
概念:
-
歐拉回路: 一筆畫, 起點等於終點.
-
尤拉路徑: 一筆畫, 起點可以不等於終點.(條件更加寬鬆).
-
尤拉圖: 存在歐拉回路的圖.
-
半尤拉圖: 僅存在尤拉路徑的圖.
找歐拉回路
存在的充要條件
A.判斷尤拉通路是否存在的方法
有向圖:圖連通, 有一個頂點出度大入度1, 有一個頂點入度大出度1, 其餘都是出度=入度.
無向圖:圖連通, 只有兩個頂點是奇數度, 其餘都是偶數度的.
B.判斷歐拉回路是否存在的方法
有向圖:圖連通, 所有的頂點出度=入度.
無向圖:圖連通, 所有頂點都是偶數度.
特殊情況:孤立點, 孤立點沒有邊相連, 沒有影響, 求解歐拉回路的時候可以直接刪掉.
下面進行簡單的證明:
起點終點為奇數度的, 先從起點到終點連任意一條邊, 可以得到一個皆為偶數度的圖. 一個皆為偶數度的圖的必定不可能是一棵樹, 必定存在一個簡單環. 得到一個簡單環之後, 將該環從圖中刪去, 仍然可以得到一個皆為偶數度的圖, 如此反覆, 最終可以將原圖分解為由許多個環組成的圖.
可以發現各個環之間不存在公共邊, 且一定可以通過某些點進行連線, 因此, 我們總是可以找到一條尤拉路徑去遍歷所有的邊.
DFS
DFS天然具有拓撲的特性, 可以得到對一個尤拉圖進行DFS, 回溯的時候將邊彈入棧中, 就可以天然得到一個尤拉路徑. 看下面程式碼.
歐拉回路為了保證時間複雜度的效能, 需要將遍歷過的邊進行刪除, 為了使後續訪問的刪點過程可以影響前面的遍歷, 需要用到引用.
程式碼:
//記錄邊的路徑 void Euler(int u) { for (int &i = h[u]; ~i; i = ne[i]) {//改為引用 int t = i / 2 + 1; if (used[t]) continue; // coloring used[t] = true; if (i & 1) t = -t; Euler(e[i]); ans[++tot] = t; if (i == -1) break; //prevent ne[-1] int t = i + 1; if (used[t]) continue; // coloring used[t] = true; Euler(e[i]); ans[++tot] = t; if (i == -1) break; //prevent ne[-1] } } void Euler(int u) { for (int &i = h[u]; ~i; i = ne[i]) { int t = i / 2 + 1, v = e[i]; //undir int t = i + 1, v = e[i]; //dir if (used[t]) continue; used[t] = true; Euler(v); ans[++tot] = v; if (i == -1) break; } }