問題
無向連結グラフ $G$ から Wilson's Algorithm で一様ランダムスパニングツリーを生成。$K$ 回試行で辺頻度を計測し、ラプラシアン擬似逆行列を用いた有効抵抗の理論値と比較する。
制約
$2 \le N \le 15$
$N - 1 \le M \le N(N-1)/2$
$1 \le K \le 1000$
入出力例
入力例 1
3 3 1000
1 2
2 3
1 3
12345
出力例 1
(理論的に各辺の有効抵抗 ≈ 2/3)
ヒント (段階的開示)
ヒント1: 方向性
Wilson: Loop-Erased Random Walk でツリー外頂点を順次取り込む。期待 $O(N \cdot t_{cover})$。
ヒント2: アプローチ
有効抵抗 $R_{eff}(u,v) = L^\dagger_{uu} + L^\dagger_{vv} - 2 L^\dagger_{uv}$ で計算。numpy.linalg.pinv を使用。
ヒント3: 誘導
辺 $(u,v)$ が URST に含まれる確率 = $R_{eff}(u, v)$(Kirchhoff の対応)。
模範解答 (Python)
import sys
import random
import numpy as np
input = sys.stdin.readline
def main():
N, M, K = map(int, input().split())
edges = []
adj = [[] for _ in range(N)]
adj_matrix = [[False] * N for _ in range(N)]
for _ in range(M):
u, v = map(int, input().split())
u -= 1; v -= 1
edges.append((u, v))
adj[u].append(v); adj[v].append(u)
adj_matrix[u][v] = adj_matrix[v][u] = True
seed = int(input())
rng = random.Random(seed)
def wilson(rng_instance):
in_tree = [False] * N
next_node = [-1] * N
tree_edges = set()
in_tree[0] = True
for i in range(1, N):
if in_tree[i]: continue
v = i
while not in_tree[v]:
nxt = rng_instance.choice(adj[v])
next_node[v] = nxt
v = nxt
v = i
while not in_tree[v]:
in_tree[v] = True
u = next_node[v]
tree_edges.add((min(v, u), max(v, u)))
v = u
return tree_edges
sample_tree = wilson(rng)
print(f"Sample URST (seed={seed}):")
edge_strs = " ".join(f"({u+1},{v+1})" for u, v in sorted(sample_tree))
print(f"Edges: {edge_strs}")
print()
edge_to_idx = {(min(u,v), max(u,v)): i for i, (u, v) in enumerate(edges)}
freq = [0] * M
for _ in range(K):
tree = wilson(rng)
for e in tree:
if e in edge_to_idx:
freq[edge_to_idx[e]] += 1
L = np.zeros((N, N))
for i in range(N):
for j in range(N):
if adj_matrix[i][j]:
L[i][j] = -1.0
L[i][i] += 1.0
Lpinv = np.linalg.pinv(L)
def R_eff(u, v):
return Lpinv[u][u] + Lpinv[v][v] - 2 * Lpinv[u][v]
print(f"Edge frequencies over {K} trials:")
for i, (u, v) in enumerate(edges):
print(f"({u+1},{v+1}): {freq[i]/K:.3f} (theoretical: {R_eff(u,v):.3f})")
print()
print("Effective resistances:")
for u, v in edges:
print(f"({u+1},{v+1}): {R_eff(u,v):.4f}")
main()
Step-by-Step 解説
1Wilson の正当性
LERW で各 URST が等確率。Aldous-Broder より高速。
LERW で各 URST が等確率。Aldous-Broder より高速。
2LERW
next_node[v] をランダム選択で上書き → ループ自然消去。3有効抵抗
ラプラシアン $L = D - A$(特異)の擬似逆行列で $R_{eff}$ を計算。$\sum R_{eff} = N - 1$(Kirchhoff)。
ラプラシアン $L = D - A$(特異)の擬似逆行列で $R_{eff}$ を計算。$\sum R_{eff} = N - 1$(Kirchhoff)。
4計算量
Wilson は $O(N \cdot t_{cover})$ 期待。$\text{pinv}$ は $O(N^3)$。
Wilson は $O(N \cdot t_{cover})$ 期待。$\text{pinv}$ は $O(N^3)$。
よくあるミス
| ミス | 原因 | 正しい書き方 |
|---|---|---|
| 有向辺扱い | 無向で両方向に追加が必要 | adj[u].append(v); adj[v].append(u) |
| next_node 未更新 | 無限ループ | 毎回上書き |
| L の逆行列を使用 | L は特異 | np.linalg.pinv(L) |
次のステップ
- Aldous-Broder との収束速度比較
- 代数的連結度 (Fiedler 値) と有効抵抗