kb84tkhrのブログ

何を書こうか考え中です あ、あと組織とは関係ないってやつです 個人的なやつ

ALDS1_11_B: Depth First Search

グラフの深さ優先探索
ACをとるためには、何回目でそのノードを訪れたかまで合わせる必要がある

データ構造は隣接リストにするか隣接行列にするか
隣接リストでいいかな

最初にざっと書いてみたのがこれ

class Node():
    def __init__(self, v):
        self.d = 0
        self.f = 0
        self.v = v

    def __repr__(self):
        return "Node({},{},{})".format(
            self.d, self.f, self.v)

def read_node():
    n = int(input())
    adj_list = [[] for _ in range(n + 1)]

    for _ in range(n):
        id, _, *v = [int(x) for x in input().split()]
        adj_list[id] = Node(v)

    return adj_list

def depth_first_search(adj_list):
    def dfs(id):
        nonlocal adj_list, timestamp

        adj_list[id].d = timestamp
        for adj_id in adj_list[id].v:
            if adj_list[adj_id].d == 0:
                timestamp += 1
                dfs(adj_id)
        timestamp += 1
        adj_list[id].f = timestamp

    timestamp = 1
    dfs(1)

def print_result(adj_list):
    for id in range(1, len(adj_list)):
        print(id, adj_list[id].d, adj_list[id].f)

def main():
    adj_list = read_node()
    depth_first_search(adj_list)
    print_result(adj_list)

if __name__ == '__main__':
    main()

サンプルデータでは成功したのでジャッジにかけてみたら
いきなり最初のテストでWA

何かなーと思ったら、頂点3を見つけられてなかった
頂点1を始点として、たどりつけるところにしか回ってなかった

未発見の頂点が残っていれば、その中の番号が一番小さい1つを新たな始点として探索を続けます。

ってとこをちゃんとやってなかった
一番最初はどこから始めたらいいんだっけ?明には書いてないみたいだけど?
と思ってたけど読み違いだ

とするとこうか

def depth_first_search(adj_list):
    def dfs(id):
        nonlocal adj_list, timestamp

        adj_list[id].d = timestamp
        for adj_id in adj_list[id].v:
            if adj_list[adj_id].d == 0:
                timestamp += 1
                dfs(adj_id)
        timestamp += 1
        adj_list[id].f = timestamp

    timestamp = 1
    for id in range(1, len(adj_list)):
        if adj_list[id].d == 0:
            dfs(id)
            timestamp += 1

なんとなく似たようなループが二か所にあるのが気になるけどこんなもんかな?

木の探索と違って、巡回済みかどうかを覚えておかないといけないけど
こういうのをイミュータブルな世界でやるにはどうしたらいいんだろう?