LoginSignup
0
0

More than 1 year has passed since last update.

[Python] UnionFind ABC214D

Last updated at Posted at 2021-08-15

ABC214D

以下では、辺の重みは相異なると仮定します。制約にそのような条件はありませんが、添字の大小による tie-break などを行えばよいです。

各 $i , (1 \leq i \leq N -1)$ ついて、$f(u, v) = w_i$ となる $(u, v)$ の総数を数えることを考えます。$f(u, v) = w_i$となるための条件は、頂点 $(u, v)$ を結ぶパスに辺 $i$ が含まれ、かつそのパスに含まれる他の辺の重みが $w_i$ より小さいことです。

重みが $w_i$ より小さい辺のみを張ったグラフを考えると、これは森(Forest グラフ理論の用語)となっており、$u_i$ と $v_i$ は必ず異なる連結成分に属します。これら二つの連結成分の一方に $u$、もう一方に $v$ が属することが、$f(u, v) = w_i$ となるための条件です。

よって、辺の重みの小さい順にグラフに追加していき、Union-Find などのデータ構造を用いて連結成分の大きさを取得することにより、この問題を解くことができます。

サンプルコード
class UF:
  def __init__(self, N):
    # vertex → root, root → size
    self.uf = [-1] * N
    self.n = N

  # find root
  def find(self, x):
    if self.uf[x] < 0: return x
    self.uf[x] = self.find(self.uf[x])
    return self.uf[x]

  def size(self, x):
    return -self.uf[self.find(x)]

  def union(self, x, y):
    x, y = self.find(x), self.find(y)
    if x == y: return
    if self.size(x) > self.size(y): x, y = y, x
    self.uf[y] += self.uf[x]
    self.uf[x] = y
    self.n -= 1

N = int(input())
E = sorted([tuple(map(int, input().split())) for _ in range(N-1)], key=lambda x: x[2])

uf = UF(N)
ans = 0
for u, v, w in E:
  u -= 1
  v -= 1
  ans += uf.size(u) * uf.size(v) * w
  uf.union(u, v)

print(ans)
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0