提出 #58867147
ソースコード 拡げる
#LC UnionFind
class UnionFind:
def __init__(self, N: int):
assert 0 <= N < 1 << 31
self._parent = [-1] * N #負なら親で、要素数 正なら子で、ひとつ親の頂点番号
self._next = [i for i in range(N)] #同一連結成分の次の頂点番号
self._direct = [i + 1 for i in range(N)] #右側で最寄りの親 親の間のみ更新する
self._Lt = 0 #暫定的な最左の親番号
#頂点Viの親を探し、経路圧縮する
def find(self, Vi: int):
Pi = Vi
#1. Viの親Piを探す
while self._parent[Pi] >= 0:
Pi = self._parent[Pi]
#2. Vi → Piの経路上のすべての頂点に対し、親をPiに変更する
while self._parent[Vi] >= 0:
#parent[Vi] ← Pi(経路圧縮) と Vi ← parent[Vi](ひとつ親に移動) を同時に行う
#代入順に注意!左辺は parent[Vi], Vi の順にすること(逆だと壊れる)
self._parent[Vi], Vi = Pi, self._parent[Vi]
return Pi
def unite(self, Ui: int, Vi: int):
#1. Ui, Viを親に置換しつつ、異なる連結成分かを評価
if ( Ui := self.find(Ui) ) == ( Vi := self.find(Vi) ):
return False
#2. union by size Uiがより大きいサイズの親になるようswapしてからマージ
if self._parent[Ui] > self._parent[Vi]:
Ui, Vi = Vi, Ui
self._parent[Ui] += self._parent[Vi]
self._parent[Vi] = Ui
#3. connect(要素の列挙)用の配列をswap
self._next[Ui], self._next[Vi] = self._next[Vi], self._next[Ui]
return True
def same(self, Ui: int, Vi: int):
return self.find(Ui) == self.find(Vi)
def size(self, Vi: int):
return - self._parent[ self.find(Vi) ]
#for v in self.connect(Vi): で、頂点Viの連結成分の要素を列挙する Vi以降は順不同
def connect(self, Vi: int):
#1. 頂点Viを出力
yield ( Pi := Vi )
#2. 頂点Viに戻ってくるまで、次の頂点に移動
while ( Pi := self._next[Pi] ) != Vi:
yield Pi
#for v in self.leader: で、親(代表値)を昇順に列挙 ならしO(親の数)
@property
def leader(self):
#1. 最も番号の小さい親を探す
while self._parent[ self._Lt ] >= 0: #子なら
self._Lt = self._direct[ self._Lt ] #当時の記録を頼りに最寄りの親に移動
#2. self._directの情報を更新しながら、超頂点Nまで移動
back = now = self._Lt
while now != N:
#a) 次の頂点に移動する。Nに到達するか、親になったらbreak
while ( now := self._direct[now] ) != N and self._parent[now] >= 0:
pass
#b) 親backから親nowの間には子しかないので、self._direct[back]を経路圧縮
self._direct[back] = now
#c) backを出力してから、back ← now
yield back
back = now
#入力高速化
import sys
input = sys.stdin.readline
#UnionFindを実行
N, Q = map(int, input().split())
UF = UnionFind(N)
for _ in range(Q):
Ti, Ui, Vi = map(int, input().split())
if Ti == 0: UF.unite(Ui, Vi)
else: print(1 if UF.same(Ui, Vi) else 0)
提出情報
ジャッジ結果
| セット名 |
Sample |
All |
| 得点 / 配点 |
0 / 0 |
100 / 100 |
| 結果 |
|
|
| セット名 |
テストケース |
| Sample |
example_00 |
| All |
example_00, random_00, random_01, random_02, random_03, random_04, random_05, random_06, random_07, random_08, random_09 |
| ケース名 |
結果 |
実行時間 |
メモリ |
| example_00 |
AC |
55 ms |
76428 KiB |
| random_00 |
AC |
156 ms |
87556 KiB |
| random_01 |
AC |
143 ms |
87640 KiB |
| random_02 |
AC |
146 ms |
85504 KiB |
| random_03 |
AC |
93 ms |
87024 KiB |
| random_04 |
AC |
144 ms |
85336 KiB |
| random_05 |
AC |
154 ms |
86000 KiB |
| random_06 |
AC |
129 ms |
88120 KiB |
| random_07 |
AC |
77 ms |
84216 KiB |
| random_08 |
AC |
126 ms |
84228 KiB |
| random_09 |
AC |
172 ms |
87524 KiB |