Constructing an Eulerian Path (Hierholzer’s Algorithm)

概要

有向グラフ \(G = (V, E)\) においてオイラー路を構築するアルゴリズム

計算量

\(O(|E|)\)

実装

import sys
readline = sys.stdin.readline
write = sys.stdout.write

def hierholzer(N, M, E):
    G = [[] for i in range(N)]
    deg = [0]*N
    rdeg = [0]*N
    for a, b in E:
        deg[a] += 1
        rdeg[b] += 1
        G[a].append(b)

    # find starting and ending vertices
    s = t = u = -1
    for i in range(N):
        if deg[i] == rdeg[i] == 0:
            continue
        df = deg[i] - rdeg[i]
        if not -1 <= df <= 1:
            return None
        if df == 1:
            if s != -1:
                return None
            s = i
        elif df == -1:
            if t != -1:
                return None
            t = i
        else:
            u = i
    v0 = (s if s != -1 else u)

    # find an Eulerian path (or circuit)
    res = []
    it = [0]*N
    st = [v0]
    *it, = map(iter, G)
    while st:
        v = st[-1]
        w = next(it[v], -1)
        if w == -1:
            res.append(v)
            st.pop()
            continue
        st.append(w)
    res.reverse()
    if len(res) != M+1:
        return None
    return res


E = [
  (2, 0), (0, 3), (0, 1), (3, 2), (1, 2),
]
print(hierholzer(4, 5, E))
# => "[0, 3, 2, 0, 1, 2]"

Verified

  • Codeforces: "508D: Tanya and Password": source (Python3, 577ms), source (PyPy3, 327ms)

参考