1. 程式人生 > 其它 >演算法專題——歐拉回路

演算法專題——歐拉回路

歐拉回路

概念:

  1. 歐拉回路: 一筆畫, 起點等於終點.

  2. 尤拉路徑: 一筆畫, 起點可以不等於終點.(條件更加寬鬆).

  3. 尤拉圖: 存在歐拉回路的圖.

  4. 半尤拉圖: 僅存在尤拉路徑的圖.


找歐拉回路

存在的充要條件

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;
    }
}

例題

ant trip

題面:

分析:


歐拉回路

題面:

分析: