歐拉路徑是圖論的起點——柯尼斯堡七橋問題的答案,讓歐拉在 1736 年建立了圖論這個領域。

問題定義

歐拉路徑:走過圖中每條邊「恰好一次」的路徑(起終點可以不同)
歐拉迴路:同上,但要回到起點

重要區別:這和漢密頓路徑(每個頂點走一次)是完全不同的問題——漢密頓是 NP-complete,歐拉可以在 O(V+E) 解決。

存在條件(充要)

無向圖

歐拉迴路:所有頂點度數為偶數 + 圖連通
歐拉路徑:恰好 0 或 2 個奇數度頂點 + 圖連通
  0 個奇數度頂點 = 等同歐拉迴路(任意頂點出發)
  2 個奇數度頂點 = 從一個奇數度頂點出發,到另一個結束

有向圖

歐拉迴路:所有頂點 入度 = 出度 + 圖弱連通
歐拉路徑:
  最多 1 個頂點 出度 - 入度 = 1 (起點)
  最多 1 個頂點 入度 - 出度 = 1 (終點)
  其餘頂點 入度 = 出度

Hierholzer 演算法

O(V+E) 找歐拉迴路。核心思路不是「一直走」,而是「走完小迴路,再插入主迴路」:

void hierholzer(int start) {
    Stack<Integer> stack = new Stack<>();
    List<Integer> path = new ArrayList<>();
    stack.push(start);
 
    while (!stack.isEmpty()) {
        int v = stack.peek();
        if (adj[v].isEmpty()) {
            path.add(v);   // 沒有剩餘邊 → 這個節點進入路徑
            stack.pop();
        } else {
            int u = adj[v].removeFirst(); // 走一條邊並刪除
            stack.push(u);
        }
    }
    Collections.reverse(path);
}

為什麼「沒有剩餘邊才進入路徑」?因為這樣能確保節點是在「所有可能延伸的路徑都走完後」才被固定到路徑中,避免提早鎖死而繞不回來。

競程常見應用

一筆畫問題:判斷是否存在歐拉路徑,就是在問能不能一筆畫完。

字串接龍:把 n 個字串排成一條鏈(首尾字元相接)。對每個字串,把首字母到末字母連一條有向邊,判斷有向歐拉路徑是否存在並找出順序。

De Bruijn 序列:包含所有 k 長二進制字串的最短序列。等價於在 de Bruijn 圖上找歐拉迴路。


歐拉路徑的存在判斷只看度數,不看具體結構——這是圖論最優雅的結論之一。