This documentation is automatically generated by online-judge-tools/verification-helper
各頂点に群 $G$ の元がラベルとして付いている無向 Graph 上 $H = (V, E)$ に対して, 以下の処理を高速に行う.
union(x, y)
: 頂点 $x$ と頂点 $y$ を結ぶ辺を追加する.find(x)
: 頂点 $x$ が属する連結成分の代表元を求める.same(x, y)
: 頂点 $x$ と頂点 $y$ は連結か?action(x, a)
: 頂点 $x$ が属する連結成分上の頂点全てに対して, $a \in G$ を作用させる。.update(x, a)
: 頂点 $x$ を $a \in G$ に更新する.get(x)
: 頂点 $x$ のラベルを求める.$H = (V,E)$ を無向 Graph とし, $G$ を群とする.
$G$ における演算, 逆元計算の計算量を $O(f)$ Times とする.
U = Union_Find_Action(N, op, unit, inv)
U.find(x)
U.union(x, y)
U.size(x)
U.same(x, y)
U.update(x, a)
U.get(x)
from typing import TypeVar, Generic, Callable
G = TypeVar('G')
class Union_Find_Group_Action(Generic[G]):
def __init__(self, N: int, op: Callable[[G, G], G], unit: G, inv: Callable[[G], G]):
# Union Find で用いる変数
self.__groups = [[x] for x in range(N)]
self.__belong = [x for x in range(N)]
# Group に関する値
self.__op = op
self.__inv = inv
# Group の積に関する変数
self.__lazy = [unit for _ in range(N)]
self.__provisional = [unit for _ in range(N)]
def find(self, x: int) -> int:
""" 頂点 x が属する連結成分の代表元を求める.
Args:
x (int): 頂点番号
Returns:
int: 頂点 x が属する連結成分の代表元
"""
return self.__belong[x]
def union(self, x: int, y: int) -> bool:
""" 頂点 x と頂点 y を結ぶ辺を追加する.
Args:
x (int): 頂点番号
y (int): 頂点番号
Returns:
bool: 元々頂点 x と頂点 y が非連結ならば True, 連結ならば False
"""
x = self.find(x)
y = self.find(y)
if x == y:
return False
if self.size(x) < self.size(y):
x, y = y, x
self.__groups[x].extend(self.__groups[y])
memo = [self.get(z) for z in self.__groups[y]]
for z, b in zip(self.__groups[y], memo):
self.__belong[z] = x
self.update(z, b)
self.__groups[y].clear()
return True
def same(self, x: int, y: int) -> bool:
return self.find(x) == self.find(y)
def size(self, x: int) -> int:
return len(self.__groups[self.find(x)])
def action(self, x: int, a: G):
""" x が属する連結成分全てに a を作用させる.
Args:
x (int): 頂点番号
a (G): 作用
"""
x = self.find(x)
self.__lazy[x] = self.__op(a, self.__lazy[x])
def update(self, x: int, a: G):
""" 頂点 x のラベルを a に更新する.
Args:
x (int): 頂点番号
a (G): 変更後のラベル
"""
self.__provisional[x] = self.__op(self.__inv(self.__lazy[self.find(x)]), a)
def get(self, x: int) -> G:
""" 頂点 x のラベルを取得する.
Args:
x (int): 頂点番号
Returns:
G: 頂点 x のラベル
"""
return self.__op(self.__lazy[self.find(x)], self.__provisional[x])
def __getitem__(self, x: int) -> G:
return self.get(x)
def __len__(self) -> int:
return len(self.__belong)
def __iter__(self):
yield from [self.get(x) for x in range(len(self))]
Traceback (most recent call last):
File "/opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/site-packages/onlinejudge_verify/documentation/build.py", line 71, in _render_source_code_stat
bundled_code = language.bundle(stat.path, basedir=basedir, options={'include_paths': [basedir]}).decode()
~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/site-packages/onlinejudge_verify/languages/python.py", line 96, in bundle
raise NotImplementedError
NotImplementedError