公式

G - Minimum XOR Path 解説 by toam


まずは頂点 \(1\) から始まる単純パスがどれくらいあるかを考えます.グラフが完全グラフ(\(M=N(N-1)/2\) のとき)だった場合,単純パスに含まれる頂点列 \((v_1,v_2,\ldots,v_k)\) としてあり得るものは \(v_1=1\) かつ \(v_i\neq v_j(i\neq j)\) を満たすものであり,これを満たすものは \({}_{N-1}P_0+{}_{N-1}P_1+\ldots+{}_{N-1}P_{N-1}\) 通りです(\({}_nP_r\) は異なる \(n\) 個のものから \(k\) 個選んで並べる方法の総数).この値は \(\Theta((N-1)!)\) であり,\(N=10\) のとき約 \(10^6\) となります.したがって,あり得る単純パスを全て調べることができます.

単純パスを全部列挙するには DFS が有効です.(最後に訪れた頂点,訪問したかどうかを確認する配列,すでに通った辺に書かれたラベルの総 XOR)を持ちながら DFS をすることで答えを求めることができます.実装例も参考にしてください.

N, M = map(int, input().split())
G = [[] * N for i in range(N)]  # 隣接頂点リスト.(頂点, 辺のラベル)をペアで持つ.
for i in range(M):
    u, v, w = map(int, input().split())
    u -= 1
    v -= 1
    G[u].append((v, w))
    G[v].append((u, w))

ans = 1 << 60
visited = [False] * N  # 訪問済みかどうかを持つリスト


def dfs(v, xor):
    global ans
    visited[v] = True  # 頂点 v を訪問済みにする

    # もし今いる頂点が N - 1 なら答えを更新する
    if v == N - 1:
        ans = min(ans, xor)

    for u, w in G[v]:
        # もし頂点 u に訪れていないなら,頂点 u に進む
        if not visited[u]:
            dfs(u, xor ^ w)
    visited[v] = False  # 訪問済みを解除する


dfs(0, 0)
print(ans)

投稿日時:
最終更新: