Pythonで理解する蟻本「2-4 食物連鎖(POJ 1182)」(p.85)
この記事は「プログラミングコンテストチャレンジブック第2版」(蟻本)の
「2-4 食物連鎖(POJ 1182)」(p.85)
のコードをPythonで書き直したものとなっています。
入力
入力例
100 7
1 2 2 2 1 2 1
101 1 2 3 1 3 5
1 2 3 3 3 1 5
解答
# 入力(Tは情報のタイプ)
N, K = map(int,input().split())
T = list(map(int,input().split()))
X = list(map(int,input().split()))
Y = list(map(int,input().split()))
# Union-Find木のソースコード
class UnionFindTree():
# n要素で初期化
def __init__(self, n):
self.n = n
self.par = list(range(n))
self.rank = [0] * n
# 木の根を求める
def find(self, x):
if self.par[x] == x:
return x
else:
self.par[x] = self.find(self.par[x])
return self.par[x]
# xとyの属する集合を併合
def unite(self, x, y):
x = self.find(x)
y = self.find(y)
if x == y:
return
if self.rank[x] < self.rank[y]:
self.par[x] = y
else:
self.par[y] = x
if self.rank[x] == self.rank[y]:
self.rank[x] += 1
# xとyが同じ集合に属するか否か
def same(self, x, y):
return self.find(x) == self.find(y)
# Union-Find木を初期化
# x, x + N, x + 2 * N を x-A, x-B, x-Cの要素とする
UFT = UnionFindTree(N * 3)
ans = 0
for i in range(K):
t = T[i]
x = X[i] - 1 # 0, ..., N - 1の範囲にする
y = Y[i] - 1
# 正しくない番号
if x < 0 or N <= x or y < 0 or N <= y:
ans += 1
continue
if t == 1:
# 「xとyは同じ種類」という情報
if UFT.same(x, y + N) or UFT.same(x, y + 2 * N):
ans += 1
else:
UFT.unite(x, y)
UFT.unite(x + N, y + N)
UFT.unite(x + N * 2, y + N * 2)
else:
# 「xとyを食べる」という情報
if UFT.same(x, y) or UFT.same(x, y + 2 * N):
ans += 1
else:
UFT.unite(x, y + N)
UFT.unite(x + N, y + 2 * N)
UFT.unite(x + 2 * N, y)
print(ans)