library_for_python

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub Kazun1998/library_for_python

:heavy_check_mark: Union Find (Disjoint Set Union)
(Union_Find/Union_Find.py)

Outline

無向グラフにおける辺の追加と連結判定を得意とするデータ構造.

Contents


Constructer

U=Union_Find(N)

find

U.find(x)

union

U.union(x,y)

size

U.size(x)

same

U.same(x,y)

members

U.members(x)

edge_count

U.edge_count(x)

is_tree

U.is_tree()

tree_count

U.tree_count()

representive

U.representative()

group_count

U.group_count()

all_group_members

U.all_group_members()

group_list

U.group_list(x,y)

refresh

U.refresh()

getitem

U[x]

setitem

U[x]=y

Required by

Verified with

Code

class Union_Find:
    __slots__ = ("__n", "parents", "rank", "edges", "__group_number")

    def __init__(self, N: int) -> None:
        """ 0, 1, ..., (N - 1) を要素に持つ Union Find を生成する.

        Args:
            N (int): 要素数
        """

        self.__n = N
        self.parents=[-1]*N
        self.rank=[0]*N
        self.edges=[0]*N
        self.__group_number = N

    def find(self, x: int) -> int:
        """ 要素 x が属している族を調べる

        Args:
            x (int): 要素

        Returns:
            int: x が属している族
        """

        a=x
        while self.parents[a]>=0:
            a=self.parents[a]

        while self.parents[x]>=0:
            y=self.parents[x]
            self.parents[x]=a
            x=y

        return a

    def union(self, x: int, y: int, force : bool = False) -> bool:
        """ 要素 x と 要素 y を同一視する.

        Args:
            x (int): 要素 x
            y (int): 要素 y
            force (bool, optional): True の場合, 必ず x が代表元になるようにマージする. Defaults to False.

        Returns:
            bool: 元々非連結ならば True, 元々連結ならば False.
        """
        x=self.find(x)
        y=self.find(y)

        if x==y:
            self.edges[x]+=1
            return False

        if (not force) and (self.rank[x] < self.rank[y]):
            x,y=y,x

        self.__group_number-=1

        self.edges[x]+=self.edges[y]+1
        self.edges[y]=0

        self.parents[x]+=self.parents[y]
        self.parents[y]=x

        if self.rank[x]==self.rank[y]:
            self.rank[x]+=1
        return True

    def size(self, x: int) -> int:
        """ 要素 x が属している族のサイズを求める

        Args:
            x (int): 要素

        Returns:
            int: 要素 x が属している族のサイズ
        """
        return -self.parents[self.find(x)]

    def same(self, x: int, y: int) -> int:
        """ 要素 x, y は同一視されているか?

        Args:
            x (int): 要素
            y (int): 要素

        Returns:
            int: x, y が同一視されていれば True, そうでなければ False
        """
        return self.find(x) == self.find(y)

    def members(self, x: int) -> list[int]:
        """ 要素 x と同一視されている要素のリスト

        Args:
            x (int): 要素

        Returns:
            list[int]: 要素 x と同一視されている要素のリスト
        """

        root = self.find(x)
        return [i for i in range(self.N) if self.find(i) == root]

    def edge_count(self, x: int) -> int:
        """ 要素 x が属している族における辺の数を求める.

        Args:
            x (int): 要素

        Returns:
            int: 要素 x が属している族における辺の数を求める
        """

        return self.edges[self.find(x)]

    def is_tree(self, x: int) -> bool:
        """ 要素 x が属する族が木かどうかを判定する.

        Args:
            x (int): 要素

        Returns:
            bool: 木ならば True, そうでなければ False
        """

        return self.size(x)==self.edges[self.find(x)]+1

    def tree_count(self) -> int:
        """ 木になっている族の数を計上する

        Returns:
            int: 木になっている族の数
        """

        return sum(self.is_tree(g) for g in self.representative())

    def representative(self) -> list[int]:
        """ 代表元のリスト

        Returns:
            list[int]: 代表元のリスト
        """
        return [i for i, x in enumerate(self.parents) if x < 0]

    @property
    def N(self):
        return self.__n

    @property
    def group_number(self) -> int:
        """ 族の個数

        Returns:
            int: 族の個数
        """

        return self.__group_number

    def all_group_members(self) -> dict[int, list[int]]:
        """ 全ての族の出力
        """
        X={r:[] for r in self.representative()}
        for k in range(self.N):
            X[self.find(k)].append(k)
        return X

    def group_list(self) -> list[int]:
        """ 各要素が属している族のリストを出力する.

        """
        return [self.find(x) for x in range(self.N)]

    def refresh(self) -> None:
        for i in range(self.N):
            self.find(i)

    def __str__(self) -> str:
        return str(list(self.all_group_members().values()))[1: -1]

    def __repr__(self) -> str:
        return f"{self.__class__.__name__}({self.N})"

    def __getitem__(self, index: int) -> int:
        return self.find(index)

    def __setitem__(self, x: int, y: int) -> None:
        self.union(x, y)
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
Back to top page