提出 #24943728


ソースコード 拡げる

from typing import List, Tuple
from heapq import heappush, heappop
import sys
sys.setrecursionlimit(10 ** 6)

class Graph:
    Inf = 10 ** 9

    @staticmethod
    def adj_list_from_directed_edge(n: int, edges: List[Tuple[int, int]]):
        g = [[] for _ in range(n)]
        for u, v in edges:
            g[u - 1].append(v - 1)
        return g

    @staticmethod
    def adj_mat_from_cost(n: int, costs: List[Tuple[int, int, int]], zero_indexed = False):
        """
        コストの情報から隣接行列を作成
        n: 頂点数
        cost: (始点, 終点, 重み), 1-indexed
        """
        g = [[Graph.Inf for x in range(n)] for y in range(n)]
        for i in range(n):
            g[i][i] = 0
        for s, e, c in costs:
            if not zero_indexed:
                s -= 1
                e -= 1
            g[s][e] = c
        return g

    @staticmethod
    def dijkstra(n: int, adj: List[List[Tuple[int, int]]], s: int):
        """
        s: 始点 からの最短距離を dijkstra 法で求める
        [params]
        n: 頂点数
        adj: adj[i] 頂点 i に隣接する頂点のインデックスと重み
        s: 始点
        """
        dist = [Graph.Inf] * n
        # (distance, node)
        hq = [(0, s)]
        dist[s] = 0
        seen = [False] * n

        while hq:
            v = heappop(hq)[1]
            seen[v] = True
            for to, cost in adj[v]:
                if seen[to] == False and dist[v] + cost < dist[to]:
                    dist[to] = dist[v] + cost
                    heappush(hq, (dist[to], to))

        return dist

    @staticmethod
    def floyd_warshall(n: int, g: List[List[int]]):
        """
        floyd_warshall法
        n: 頂点数
        g: 隣接行列
        """
        for k in range(n):
            for i in range(n):
                for j in range(n):
                    g[i][j] = min(g[i][j], g[i][k] + g[k][j])

        return g

    @staticmethod
    def scc(n: int, edges: List[Tuple[int, int]]):
        """
        強連結成分分解
        <https://hkawabata.github.io/technical-note/note/Algorithm/graph/scc.html>
        <https://www.slideshare.net/hcpc_hokudai/study-20150107>
        <https://pione.hatenablog.com/entry/2021/03/11/232159>
        """
        label = { i: -1 for i in range(n) }

        def dfs(s: int):
            # print(s)
            for i in adj[s]:
                if not dfs.visited[i]:
                    dfs.visited[i] = True
                    dfs(i)

                    label[i] = dfs.cnt
                    dfs.cnt += 1

        dfs.cnt = 0
        dfs.visited = [False] * n

        def dfs2(s: int):
            dfs2.ans.append(s)
            for i in inv_adj[s]:
                if not dfs2.visited[i]:
                    dfs2.visited[i] = True
                    dfs2(i)

        dfs2.visited = [False] * n

        # ステップ1: 帰りがけ順に番号ふる
        adj = Graph.adj_list_from_directed_edge(n, edges)
        for i in range(n):
            if dfs.visited[i]:
                continue

            dfs.visited[i] = True
            dfs(i)
            label[i] = dfs.cnt
            dfs.cnt += 1

        # ステップ2: 番号大きい順にDFS
        inv_edges = [(t, f) for f, t in edges]
        inv_adj = Graph.adj_list_from_directed_edge(n, inv_edges)
        label_swap = { v: k for k, v in label.items() }
        ans = []
        for i in reversed(range(n)):
            if i not in dict.keys(label_swap):
                continue
            v = label_swap[i]
            if dfs2.visited[v]:
                continue
            dfs2.ans = []
            dfs2.visited[v] = True
            dfs2(v)
            ans.append(dfs2.ans)
        
        return ans

if __name__ == "__main__":
    n, m = map(int, input().split())
    edges = []
    for _ in range(m):
        a, b = list(map(int, input().split()))
        edges.append((a, b))

    sccs = Graph.scc(n, edges)
    # print(sccs)
    k = 0
    for s in sccs:
        k += len(s) * (len(s) - 1) // 2
    print(k)

提出情報

提出日時
問題 021 - Come Back in One Piece(★5)
ユーザ wakameTech
言語 PyPy3 (7.3.0)
得点 5
コード長 4219 Byte
結果 AC
実行時間 936 ms
メモリ 298420 KiB

ジャッジ結果

セット名 Sample All
得点 / 配点 0 / 0 5 / 5
結果
AC × 2
AC × 30
セット名 テストケース
Sample sample_01.txt, sample_02.txt
All in01.txt, in02.txt, in03.txt, in04.txt, in05.txt, in06.txt, in07.txt, in08.txt, in09.txt, in10.txt, in11.txt, in12.txt, in13.txt, in14.txt, in15.txt, in16.txt, in17.txt, in18.txt, in19.txt, in20.txt, in21.txt, in22.txt, in23.txt, in24.txt, in25.txt, in26.txt, in27.txt, in28.txt, sample_01.txt, sample_02.txt
ケース名 結果 実行時間 メモリ
in01.txt AC 114 ms 74580 KiB
in02.txt AC 117 ms 76000 KiB
in03.txt AC 133 ms 77848 KiB
in04.txt AC 88 ms 74352 KiB
in05.txt AC 85 ms 74400 KiB
in06.txt AC 115 ms 75660 KiB
in07.txt AC 92 ms 74560 KiB
in08.txt AC 129 ms 76504 KiB
in09.txt AC 89 ms 74612 KiB
in10.txt AC 94 ms 74376 KiB
in11.txt AC 113 ms 75604 KiB
in12.txt AC 94 ms 74344 KiB
in13.txt AC 106 ms 75740 KiB
in14.txt AC 108 ms 75876 KiB
in15.txt AC 107 ms 75656 KiB
in16.txt AC 133 ms 79268 KiB
in17.txt AC 138 ms 77320 KiB
in18.txt AC 93 ms 74400 KiB
in19.txt AC 112 ms 75864 KiB
in20.txt AC 88 ms 74368 KiB
in21.txt AC 371 ms 115640 KiB
in22.txt AC 936 ms 238940 KiB
in23.txt AC 811 ms 179436 KiB
in24.txt AC 839 ms 179176 KiB
in25.txt AC 858 ms 298420 KiB
in26.txt AC 762 ms 161508 KiB
in27.txt AC 583 ms 200904 KiB
in28.txt AC 538 ms 153096 KiB
sample_01.txt AC 88 ms 74400 KiB
sample_02.txt AC 90 ms 74384 KiB