library

This documentation is automatically generated by competitive-verifier/competitive-verifier

View the Project on GitHub hidehic0/library

:heavy_check_mark: libs/graph.py

Verified with

Code

# グラフ構造
# 無向グラフ
from collections import deque


class Graph:
    def __init__(self, N: int, dire: bool = False) -> None:
        """グラフ構造体

        Nは頂点数、direは有向グラフかです
        """
        self.N = N
        self.dire = dire
        self.grath = [[] for _ in [0] * self.N]
        self.in_deg = [0] * N

    def new_side(self, a: int, b: int) -> None:
        """aとbを辺で繋ぎます

        有向グラフなら、aからbだけ、無向グラフなら、aからbと、bからaを繋ぎます
        注意 0-indexedが前提
        """
        self.grath[a].append(b)
        if self.dire:
            self.in_deg[b] += 1

        if not self.dire:
            self.grath[b].append(a)

    def side_input(self) -> None:
        """標準入力で、新しい辺を追加します"""
        a, b = map(lambda x: int(x) - 1, input().split())
        self.new_side(a, b)

    def input(self, M: int) -> None:
        """標準入力で複数行受け取り、各行の内容で辺を繋ぎます"""
        for _ in [0] * M:
            self.side_input()

    def get(self, a: int) -> list[int]:
        """頂点aの隣接頂点を出力します"""
        return self.grath[a]

    def all(self) -> list[list[int]]:
        """グラフの隣接リストをすべて出力します"""
        return self.grath

    def topological(self, unique: bool = False) -> list[int]:
        """トポロジカルソートします

        有向グラフ限定です

        引数のuniqueは、トポロジカルソート結果が、一意に定まらないとエラーを吐きます
        閉路がある、または、uniqueがTrueで一意に定まらなかった時は、[-1]を返します
        """
        if not self.dire:
            msg = "グラフが有向グラフでは有りません (╥﹏╥)"
            raise ValueError(msg)

        in_deg = self.in_deg[:]

        S: deque[int] = deque([])
        order: list[int] = []

        for i in range(self.N):
            if in_deg[i] == 0:
                S.append(i)

        while S:
            if unique and len(S) != 1:
                return [-1]

            cur = S.pop()
            order.append(cur)

            for nxt in self.get(cur):
                in_deg[nxt] -= 1

                if in_deg[nxt] == 0:
                    S.append(nxt)

        if sum(in_deg) > 0:
            return [-1]

        return [x for x in order]


class GraphW:
    def __init__(self, N: int, dire: bool = False) -> None:
        """重み付きグラフ"""
        self.N = N
        self.dire = dire
        self.grath = [[] for _ in [0] * self.N]

    def new_side(self, a: int, b: int, w: int) -> None:
        """aとbを辺で繋ぎます

        有向グラフなら、aからbだけ、無向グラフなら、aからbと、bからaを繋ぎます
        注意 0-indexedが前提
        """
        self.grath[a].append((b, w))
        if not self.dire:
            self.grath[b].append((a, w))

    def side_input(self) -> None:
        """標準入力で、新しい辺を追加します"""
        a, b, w = map(lambda x: int(x) - 1, input().split())
        self.new_side(a, b, w + 1)

    def input(self, M: int) -> None:
        """標準入力で複数行受け取り、各行の内容で辺を繋ぎます"""
        for _ in [0] * M:
            self.side_input()

    def get(self, a: int) -> list[tuple[int]]:
        """頂点aの隣接頂点を出力します"""
        return self.grath[a]

    def all(self) -> list[list[tuple[int]]]:
        """グラフの隣接リストをすべて出力します"""
        return self.grath
Back to top page