library_for_python

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

View the Project on GitHub Kazun1998/library_for_python

:warning: 色付き Union Find
(Union_Find/Coloring_Union_Find.py)

Outline

Union Find の機能に加え, 各連結成分に色という情報を持たせ, マージによって連結成分がまとめられる際, その連結成分の色は元の2つの連結成分の色から決定される.

Theory

$G=(V,E)$ を無向グラフとし, $X$ を色の集合とする. また, 色の基底状態として, ${\rm unit} \in X$ とする.

Contents


Constructer

U=Coloring_Union_Find(N, merge, unit)

find

U.find(x)

union

U.union(x,y)

size

U.size(x)

same

U.same(x,y)

update

U.update(x, color)

get

U.get(x)

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

Code

from typing import TypeVar, Callable, Generic

M = TypeVar('M')
class Coloring_Union_Find(Generic[M]):
    __slots__=("n", "parents", "rank", "data", "merge", "__group_number")

    def __init__(self, N: int, merge: Callable[[M, M], M], unit: M):
        """ N 要素で初期状態を unit として初期化する.

        Args:
            N (int): 要素数
            merge (Callable[[M, M], M]): Monoid M の合成の方法
            unit (M): 基底状態
        """

        self.n=N
        self.parents=[-1]*N
        self.data=[unit]*N
        self.rank=[0]*N
        self.merge=merge
        self.__group_number=N

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

        Args:
            x (int): 要素

        Returns:
            int: 要素 x の属している族の代表元
        """
        V=[]
        while self.parents[x]>=0:
            V.append(x)
            x=self.parents[x]

        for v in V:
            self.parents[v]=x
        return x

    def union(self, x: int, y: int) -> None:
        """ 要素 x,y を同一視し, それぞれが持っている族の色を統合する.

        Args:
            x (int): 要素 1
            y (int): 要素 2
        """

        x=self.find(x)
        y=self.find(y)

        if x==y:
            return

        self.__group_number-=1

        self.data[x]=self.data[y]=self.merge(self.data[x], self.data[y])

        if self.rank[x]<self.rank[y]:
            x,y=y,x

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

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

    def size(self, x: int) -> int:
        """ 要素 x の属している族の要素の数.

        Args:
            x (int): 要素

        Returns:
            int: 要素数
        """

        return -self.parents[self.find(x)]

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

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

        Returns:
            bool: 同一視されているならば True
        """
        return self.find(x) == self.find(y)

    def update(self, x: int, color: M) -> None:
        """ 要素 x の属する族の色を color に変更する.

        Args:
            x (int): 要素
            color (M): 色
        """

        self.data[self.find(x)]=color

    def get(self, x: int) -> M:
        """ 要素 x の属する族の色を求める.

        Args:
            x (int): 要素

        Returns:
            M: 要素 x の属する族の色
        """
        return self.data[self.find(x)]

    def members(self, x: int) -> list[int]:
        """ 要素 x が属している族の要素.
        ※族の要素の個数が欲しいときは size を使うこと!!

        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 roots(self) -> list[int]:
        """ 族の名前のリスト

        Returns:
            list[int]: 各要素が族のリスト
        """
        return [i for i,x in enumerate(self.parents) if x < 0]

    def group_count(self) -> int:
        """ 族の個数 (len(self.roots) よりも高速)

        Returns:
            int: 族の個数
        """
        return self.__group_number

    def all_group_members(self) -> dict[int, list[int]]:
        """ 全ての族の出力

        Returns:
            dist[int, list[int]]: key が代表元, value が key が属する族の要素からなるリスト
        """

        X={r:[] for r in self.roots()}
        for k in range(self.n):
            X[self.find(k)].append(k)
        return X

    def list(self) -> list[M]:
        """ 各要素が属している族の色のリスト

        Returns:
            list[M]: 各要素が属している族の色のリスト
        """
        return [self.get(x) for x in range(self.n)]

    def map(self) -> dict[int, M]:
        """ 代表元とその代表元が属している族の色の辞書

        Returns:
            dict[int, M]: key が代表元, value が key が属する族の色
        """
        return { root: self.get(root) for root in self.roots()}

    def __str__(self) -> str:
        segments = [f"({self.get(x)}) {g}" for x, g in self.all_group_members().items()]
        return ", ".join(segments)

    def __repr__(self) -> str:
        return f"Coloring Union Find: {str(self)}"

    def __getitem__(self, index) -> M:
        return self.data[self.find(index)]

    def __setitem__(self, index, value) -> None:
        self.data[self.find(index)]=value
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