PythonでAizu Online Judgeを解く/GRL_3_B - Bridges
Posted on
橋
無向グラフ \(G (V, E)\) の橋を列挙してください(削除すると連結成分が増えるような辺を橋と呼ぶものとします)
制約
- \(1 \leq |V| \leq 100,000\)
- \(0 \leq |E| \leq 100,000\)
- グラフ \(G\) は連結
- グラフ \(G\) は平行辺を持たない
- グラフ \(G\) は自己ループを持たない
入力
%python
def input(f):
global v, e
global s, t
v, e = map(int, f.readline().split())
s = [-1 for _ in range(e)]
t = [-1 for _ in range(e)]
for i in range(e):
s[i], t[i] = map(int, f.readline().split())サンプル入力 #1
%sh cat <<-EOF > /tmp/input1 4 4 0 1 0 2 1 2 2 3 EOF
%python
with open('/tmp/input1') as f:
input(f)
print(v, e)
print(s)
print(t)(4, 4) [0, 0, 1, 2] [1, 2, 2, 3]
サンプル入力 #2
%sh cat <<-EOF > /tmp/input2 5 4 0 1 1 2 2 3 3 4 EOF
(5, 4) [0, 1, 2, 3] [1, 2, 3, 4]
考え方
関節点を求めたときと同様に lowlink を利用すると良さそうです 🤔
GRL_3_A:
https://hiroyuki.sano.ninja/notes/78e36032-06f0-42b6-8e56-fc0a08ca05a2
実装
%python
import sys
sys.setrecursionlimit(1000000)
def solve():
g = [[] for _ in range(v)]
for i in range(e):
g[s[i]].append(t[i])
g[t[i]].append(s[i])
used = [False for _ in range(v)]
ord = [-1 for _ in range(v)]
low = [10**6 for _ in range(v)]
res = []
def rec(cur, prev, d):
if used[cur]:
return
used[cur] = True
ord[cur] = d
low[cur] = ord[cur]
cnt = 0
for nxt in g[cur]:
if not used[nxt]:
cnt += 1
rec(nxt, cur, d+1)
low[cur] = min(low[cur], low[nxt])
if prev >= 0 and ord[cur] < low[nxt]:
res.append((min(cur, nxt), max(cur, nxt)))
elif nxt != prev:
low[cur] = min(low[cur], ord[nxt])
if prev == -1 and (cnt >= 2 or len(g[cur]) == 1):
for nxt in g[cur]:
res.append((min(cur, nxt), max(cur, nxt)))
rec(0, -1, 0)
for src, dst in sorted(res):
print('{} {}'.format(src, dst))サンプル
%python
with open('/tmp/input1') as f:
input(f)
solve()2 3
%python
with open('/tmp/input2') as f:
input(f)
solve()0 1 1 2 2 3 3 4
Wrong Answer #1: 根は cnt >= 2 or 元グラフの次数が 1
%sh curl -s https://judgedat.u-aizu.ac.jp/testcases/GRL_3_B/4/in > /tmp/in4.txt head /tmp/in4.txt
3 2 0 1 0 2
%python
with open('/tmp/in4.txt') as f:
input(f)
solve()0 1 0 2
Wrong Answer #2: 関節点を持つ辺が必ずしも橋にはならない
%sh curl -s https://judgedat.u-aizu.ac.jp/testcases/GRL_3_B/8/in > /tmp/in8.txt head /tmp/in8.txt
5 5 0 1 1 2 1 3 2 3 3 4
%python
with open('/tmp/in8.txt') as f:
input(f)
solve()0 1 3 4
辺 (1, 2) が橋ではありませんでした
- if prev >= 0 and ord[cur] <= low[nxt]:
+ if prev >= 0 and ord[cur] < low[nxt]:
res.append((cur, nxt))
%python
with open('/tmp/in8.txt') as f:
input(f)
solve()0 1 3 4
Wrong Answer #3: 出力は各レコードも昇順
%sh curl -s https://judgedat.u-aizu.ac.jp/testcases/GRL_3_B/11/in > /tmp/in11.txt head /tmp/in11.txt
16 19 0 1 0 3 0 2 1 3 2 3 3 6 4 6 5 6 6 7
%python
with open('/tmp/in11.txt') as f:
input(f)
print('''
%html
<div id="stage11"></div>
<script>
(function() {
function visualize1() {
const graph = new Graph(d3.select('#stage11'));
''')
for i in range(v):
print('graph.addNode("{}");'.format(i))
for i in range(e):
print('graph.addEdge("{}", "{}");'.format(s[i], t[i]))
print('''
graph.update();
setTimeout(function() {
graph.simulation.stop();
}, 3000);
}
const wait1 = setTimeout(visualize1, 2000);
window.d3MinJS.addEventListener('load', function() {
clearTimeout(wait1);
visualize1();
});
})();
</script>
''')%python
with open('/tmp/in11.txt') as f:
input(f)
solve()3 6 4 6 5 6 6 7 6 9 9 12 10 11
(6, 4) を (4, 6) にする必要があります
Wrong Answer #4: 並べ替えたあとのリストを並べ替える
%sh curl -s https://judgedat.u-aizu.ac.jp/testcases/GRL_3_B/20/in > /tmp/in20.txt head /tmp/in20.txt
9 10 0 1 0 2 1 4 2 5 3 4 3 6 4 5 4 7 5 7
%python
with open('/tmp/in20.txt') as f:
input(f)
solve()3 4 3 6 7 8
1行目と2行目が逆になっています
アニメーション
%python