Problem:


  MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

Depth First Search

  Depth-first search (DFS) follows the strategy to search ”deeper” in the graph whenever possible. In DFS, edges are recursively explored out of the most recently discovered vertex $v$ that still has unexplored edges leaving it. When all of $v$'s edges have been explored, the search ”backtracks” to explore edges leaving the vertex from which $v$ was discovered.

  This process continues until all the vertices that are reachable from the original source vertex have been discovered. If any undiscovered vertices remain, then one of them is selected as a new source and the search is repeated from that source.

  DFS timestamps each vertex as follows:

$d[v]$ records when $v$ is first discovered.

$f[v]$ records when the search finishes examining $v$’s adjacency list.

  Write a program which reads a directed graph $G = (V, E)$ and demonstrates DFS on the graph based on the following rules:

$G$ is given in an adjacency-list. Vertices are identified by IDs $1, 2,... n$ respectively.

IDs in the adjacency list are arranged in ascending order.

The program should report the discover time and the finish time for each vertex.

When there are several candidates to visit during DFS, the algorithm should select the vertex with the smallest ID.

The timestamp starts with 1.

Input

  In the first line, an integer $n$ denoting the number of vertices of $G$ is given. In the next $n$ lines, adjacency lists of $u$ are given in the following format:

$u$ $k$ $v_1$ $v_2$ ... $v_k$

$u$ is ID of the vertex and $k$ denotes its degree. $v_i$ are IDs of vertices adjacent to $u$.

Output

  For each vertex, print $id$, $d$ and $f$ separated by a space character in a line. $id$ is ID of the vertex, $d$ and $f$ is the discover time and the finish time respectively. Print in order of vertex IDs.

Constraints

$1 \leq n \leq 100$

Sample Input 1

4
1 1 2
2 1 4
3 0
4 1 3

Sample Output 1

1 1 8
2 2 7
3 4 5
4 3 6

Sample Input 2

6
1 2 2 3
2 2 3 4
3 1 5
4 1 6
5 1 6
6 0

Sample Output 2

1 1 12
2 2 11
3 3 8
4 9 10
5 4 7
6 5 6

  This is example for Sample Input 2 (discover/finish)

Reference

Introduction to Algorithms, Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein. The MIT Press.



Sample input:
4
1 1 2
2 1 4
3 0
4 1 3


Sample output:
1 1 8
2 2 7
3 4 5
4 3 6

Submission status: Accepted

Solution code:
# 隣接リスト
n = int(input())

graph = []
for _ in range(n):
    tmp = list(map(int, input().split()))
    if tmp[1] == 0:
        graph.append([])
    else:
        graph.append(tmp[2:])

#print(graph)
check = [0]*n
count = 0
go = [0]*n
back = [0]*n

def dfs(v):
    #print(v)
    global count
    if check[v] == 0:
        check[v] = 1
        count += 1
        go[v] = count
        tolist = graph[v]
        if len(tolist) > 0:
            for i in tolist:
                dfs(i-1)
        count += 1
        back[v] = count

while True:
    if 0 in check:
        k = check.index(0)
        dfs(k)
    else:
        break

#print("check\t:{}".format(check))
#print("go\t:{}".format(go))
#print("back\t:{}".format(back))

for i in range(n):
    print("{} {} {}".format(i+1, go[i], back[i]))

Submission status: Accepted

Solution code:
n=int(input())
G=[]
for i in range(n):
    u,k,*l=map(int,input().split())
    G.append(l)
#print(G)
log_finish=[0]*n
log_start=[0]*n

from collections import deque
def dfs(G):
    q=deque()
    for i in range(n,0,-1):
        q.append((i,-1,0))
    log_finish[0]=1
    log_start[0]=1
    cnt=0
    while q:
        #print(q,cnt)
        V,P,S=q.pop()
        if log_finish[V-1]==0 or log_finish[V-1]==log_start[V-1]:
            cnt+=1
            if not log_finish[V-1]:log_start[V-1]=cnt
            log_finish[V-1]=cnt
        #print(V,P,S,cnt)


        if S==0:
            #下に遷移していくときの処理
            q.append((V,P,1))
            l=[]
            if not G[V-1]:continue
            for new_v in G[V-1]:
                if log_start[new_v-1]!=0:continue
                l.append((new_v,V,0))
            q+=l[::-1]

dfs(G)
for i in range(n):
    print(i+1,log_start[i],log_finish[i])

Submission status: Accepted

Solution code:
def dfs(v, u=0):
    global n, t, d, f, reached
    if len(reached) == n:
        return

    d[u] = t
    t += 1

    reached.add(u + 1)
    for ui in range(v[u][1]):
        next = v[u][2 + ui]
        if next in reached:
            continue
        dfs(v, next - 1)

    f[u] = t
    t += 1


n = int(input())
v = []
for _ in range(n):
    v.append(list(map(int, input().split())))

t = 1
d = [0] * n
f = [0] * n
reached = set()


for ui in range(n):
    if ui + 1 not in reached:
        dfs(v, ui)

for ui in range(n):
    print('%d %d %d' % (ui + 1, d[ui], f[ui]))

Submission status: Accepted

Solution code:
# DFS(再帰） v:頂点
def DFS(v,dis,fin):
  global time
  # 訪問したので発見時刻を記入
  dis[v] = time
  time += 1
  
  # vに隣接している頂点をみる
  for u in V[v]:
    if dis[u] is None:
      DFS(u,dis,fin)
  
  # 処理が完了したので完了時刻を記入
  fin[v] = time
  time += 1
  
n = int(input())
# 0番目を始点として初期化
V = [[i for i in range(n)]]

for i in range(n):
  _, __, *a = map(int, input().split())
  V.append(a)

dis = [None]*(n+1)# 頂点を発見した時刻
fin = [None]*(n+1)# 頂点の完了時刻
time = 0
DFS(0,dis,fin)

for i in range(1,n+1):
  print(i, dis[i], fin[i])

Submission status: Accepted

Solution code:
n = int(input())

A = [[] for i in range(n)]

for i in range(n):
  A[i] = list(map(int, input().split()))

B = [[0 for i in range(2)] for j in range(n)]
order = []

time = 0

def dfs(n, num):
  global time
  while time < 2*n:
    a = num
    time += 1
    if B[num-1][0] == 0: # まだ発見していないとき
      if A[num-1][1] != 0: # 次の頂点があるとき
        order.append(A[num-1][0]) # 発見したことを記録する
        B[num-1][0] = time # 発見時刻を記録する
        A[num-1][1] -= 1 # 次の頂点数を１減らす
        if B[A[num-1][2]-1][0] == 0: # 次の頂点がまだ発見されていないとき
          num = A[num-1].pop(2) # 次の頂点に移動
        else: # 次の頂点が発見済みのとき
          del A[num-1][2] # 次の頂点をルートから削除
      else: # 次の頂点がないとき
        l = len(order) # これまで経由した頂点数
        order.append(A[num-1][0]) # 発見したことを記録する
        order.append(A[num-1][0]) # 調べ終えたことを記録する
        B[num-1][0] = time # 発見時刻を記録する
        time += 1 # 時刻を１進める
        B[num-1][1] = time # 調査終了時刻を記録する
        num = order[l-1] # １つ前の頂点に戻る
    elif  B[num-1][1] == 0: # 発見しているが、調べ終えていないとき
      if A[num-1][1] == 0: # 次の頂点がないとき
        order.append(A[num-1][0]) # 調べ終えたことを記録する
        B[num-1][1] = time # 調査終了時刻を記録する
        m = order.index(num) # 発見した順番を調べる
        num = order[m-1] # 発見する前の頂点に移動
      else: # 次の頂点があるとき
        A[num-1][1] -= 1 # 次の頂点数を１減らす
        order.append(A[num-1][0]) # 経由したことを記録する
        if B[A[num-1][2]-1][0] == 0: # 次の頂点がまだ発見されていないとき
          num = A[num-1].pop(2) # 次の頂点に移動
        else: # 次の頂点が発見済みのとき
          del A[num-1][2] # つぎの頂点をルートから削除
        time -= 1 # 時刻を戻す
    else: # すでに調査終了した頂点に移動したとき
      l = len(order) # これまで経由した頂点数
      num = order[l-1] # １つ前の頂点に戻る
      time -= 1 # 時刻を戻す
      if num == a:
        break

for i in range(n):
  if B[i][0] == 0:
    dfs(n, A[i][0])

for i in range(n):
  print(str(i+1) + " ", end="")
  print(" ".join(map(str, B[i])))

Submission status: Accepted

Solution code:
G = {}
N = int(input())
for _ in range(N):
    L = list(map(int, input().split()))
    G[L[0]] = L[2:]

# print(G)
d = [-1] * N
f = [-1] * N
q = [1]
visited = [False] * N

time = 1


def dfs(v):
    global time
    visited[v-1] = True

    for nv in G[v]:
        if d[nv-1] < 0:
            d[nv-1] = time
            time += 1
        if not visited[nv-1]:
            dfs(nv)

    f[v-1] = time
    time += 1


for i in range(1, N+1):
    if not visited[i-1]:
        d[i-1] = time
        time += 1
        dfs(i)

for i in range(N):
    print(i+1, d[i], f[i])

Submission status: Accepted

Solution code:
NOT_FOUND = 0
FOUND = 1
FINISHED = 2


class Stack(object):
    def __init__(self):
        self._stack = []

    def push(self, val):
        self._stack.append(val)

    def pop(self):
        val = self._stack[-1]
        del self._stack[-1]
        return val

    def top(self):
        if len(self._stack) > 0:
            return self._stack[-1]
        else:
            return None

    def is_stacked(self, val):
        if len(self._stack) > 0:
            return val in self._stack
        else:
            return None

    def get_len(self):
        return len(self._stack)


def parse_line(line):
    vals = [int(v) for v in line.split(' ')]
    node, n_node, nodes = vals[0], vals[1], vals[2:]
    # convert zero origin
    nodes = [n - 1 for n in nodes]
    return node, n_node, nodes


def main():
    # get input
    n = int(input().strip())
    graph = []
    for _ in range(n):
        line = input().strip()
        _, _, nodes = parse_line(line)
        graph.append(nodes)

    # initialize
    stack = Stack()
    stats = [NOT_FOUND for _ in range(n)]
    found_times = [None for _ in range(n)]
    finished_times = [None for _ in range(n)]
    counter = 0

    # dfs
    while sum(stats) < n * FINISHED:
        counter += 1
        init_node = None
        for node in range(n):
            if stats[node] == NOT_FOUND:
                init_node = node
                break
        assert init_node is not None
        stack.push(init_node)
        stats[init_node] = FOUND
        found_times[init_node] = counter

        while stack.get_len() > 0:
            counter += 1
            crr_node = stack.top()
            adj_nodes = graph[crr_node]
            for adj_node in adj_nodes:
                # exist not stacked node
                if stats[adj_node] == NOT_FOUND:
                    found_times[adj_node] = counter
                    stats[adj_node] = FOUND
                    stack.push(adj_node)
                    crr_node = adj_node
                    break
            else:
                # not exist not stacked node
                finished_times[crr_node] = counter
                stats[crr_node] = FINISHED
                stack.pop()
                crr_node = stack.top()

    for i in range(n):
        print('{} {} {}'.format(i + 1, found_times[i], finished_times[i]))


if __name__ == '__main__':
    main()

Submission status: Accepted

Solution code:
ii = lambda : int(input())
mi = lambda : map(int,input().split())
li = lambda : list(map(int,input().split()))

class tree:
    def __init__(self,n):
        self.n = n
        self.vlist = [None]*self.n
        self.start = [None]*self.n
        self.finish = [None]*self.n
        self.time = 0
    
    def add(self,n,v):
        v.sort()
        self.vlist[n] = v

    def search(self,u):
        if self.start[u] != None:
            return
        else:
            self.time += 1
            self.start[u] = self.time

            for i in self.vlist[u]:
                self.search(i-1)

            self.time += 1
            self.finish[u] = self.time
            return

n = ii()
t = tree(n)

for i in range(n):
    vk = li()
    u = vk[0]
    k = vk[1]
    v = vk[2:]
    t.add(u-1,v)

for i in range(n):
    t.search(i)

for i in range(n):
    print(i+1, t.start[i], t.finish[i])

Submission status: Accepted

Solution code:
from typing import List


def alds_1_11a():
    n = int(input())
    for i in range(n):
        u, k, *v = map(int, input().split())
        a = [0] * n
        for i_v in v:
            index_v = i_v - 1
            a[index_v] = 1
        print(*a)
    return


def print_matrices_list(matrices_list):
    for index_row in range(len(matrices_list)):
        print(*matrices_list[index_row])
    return


# def depth_first_search(u, stack, color, d):
#     stack.append(u)
#     color[u] = 1
#     while len(stack) != 0:
#     pass


def accept_adjacency_list() -> List[List[int]]:
    n = int(input())
    adjancy_list = []
    for i in range(n):
        list_u = list(map(int, input().split()))
        adjancy_list.append(list_u)
    return adjancy_list


def adjacency_list2adjacency_matrices(adj_list: List[List[int]]) -> List[List[int]]:
    adjancy_matrices = []
    n = len(adj_list)
    for list_u_i in adj_list:
        id_u, degree_k, *list_v = list_u_i
        list_row = [0] * n
        for v_i in list_v:
            list_row[v_i - 1] = 1
        adjancy_matrices.append(list_row)
    return adjancy_matrices


def dfs(adj_mat):
    n = len(adj_mat)
    list_colors = [0] * n  # 0:white, 1:gray, 2:black
    time = 0
    d = [0] * n  # 最初に訪問した頂点uの発見時刻
    f = [0] * n  # uの隣接リストを調べ終えた完了時刻

    for u in range(n):
        if list_colors[u] == 0:
            list_colors, time, d, f = dfs_visit(u, list_colors, adj_mat, d, f, time)

    for u in range(n):
        print(u + 1, d[u], f[u])
    return


def dfs_visit(u: int, list_colors: list, adj_mat: list, d: list, f: list, time: int):
    list_colors[u] = 1  # uを訪問
    time += 1
    d[u] = time
    for v in range(len(list_colors)):  # v:次に探索する場所
        if adj_mat[u][v] == 0:  # uからvに行く辺がないなら次へ
            continue
        if list_colors[v] == 0:  # uからvに道があるかつ行ったことがないなら行く。
            list_colors, time, d, f = dfs_visit(
                u=v, list_colors=list_colors, adj_mat=adj_mat, d=d, f=f, time=time
            )
    list_colors[u] = 2
    time += 1
    f[u] = time
    return list_colors, time, d, f


if __name__ == "__main__":
    # init
    adjacency_list = accept_adjacency_list()
    adjacency_matirces = adjacency_list2adjacency_matrices(adj_list=adjacency_list)

    dfs(adj_mat=adjacency_matirces)

Submission status: Accepted

Solution code:
N = int(input())
UK = [list(map(int,input().split())) for _ in range(N)]

class Graph:
    def __init__(self,vertex,edge):
        self.v = vertex
        self.e = edge
        self.v_color = [False for _ in range(N)]

    def color(self,u):
        self.v_color[u-1] = True

    def v_exists(self,u):
        flag = False
        for v in self.v:
            if (u,v) in self.e and self.v_color[v-1] == False:
                flag = True
                break
        return flag

V = [i+1 for i in range(N)]
E = []
for i in range(N):
    for j in range(len(UK[i])-2):
        E.append((i+1,UK[i][j+2]))

g = Graph(V,E)

ts = [[0 for _ in range(2)] for _ in range(N+1)]
time = 0

def dfs(u):
    global time
    time += 1
    g.color(u)
    if ts[u-1][0] == 0:
        ts[u-1][0] = time
    while g.v_exists(u):
        for v in g.v:
            if (u,v) in g.e and g.v_color[v-1] == False:
                dfs(v)
    time += 1
    if ts[u-1][1] == 0:
        ts[u-1][1] = time

for i in range(N):
    if g.v_color[i] == False:
        dfs(i+1)

for i in range(N):
    print(i+1,ts[i][0],ts[i][1])

Submission status: Accepted

Solution code:
n = int(input())
E = [[]]*n

for i in range(n):
    inputs = list(map(int, input().split()))
    if inputs[1]==0:
        continue
    else:
        for j in inputs[2:]:
            E[i] = E[i] + [j-1]

beg = [-1]*n
fin = [-1]*n  

t = 0      
def f(i):
    global t
    #print(i,t)
    t += 1
    beg[i] = t
    for c in E[i]:
        if beg[c]>0:
            continue
        else:
            f(c)
    t+=1
    fin[i] = t
    

for i in range(n):
    if beg[i]<0:
        f(i)
for i in range(n):
    print(i+1, beg[i], fin[i])

Submission status: Accepted

Solution code:
import heapq
from collections import deque
from enum import Enum
import sys
import math
from _heapq import heappush, heappop

BIG_NUM = 2000000000
MOD = 1000000007
EPS = 0.000000001

global current_time
global visited,go_time,back_time
global G


def dfs(node_id):
    global current_time #書かないとローカル変数扱いされる
    go_time[node_id] = current_time
    current_time += 1

    for next_node in G[node_id]:

        if visited[next_node] == True:
            continue
        visited[next_node] = True
        dfs(next_node)

    back_time[node_id] = current_time
    current_time += 1


V = int(input())

G = [[] for i in range(V)]

visited = [False]*V

go_time = [0]*V
back_time = [0]*V

for loop in range(V):
    node_id,num,*tmp_adj = list(map(int,input().split()))
    node_id -= 1
    for i in range(num):
        G[node_id].append(tmp_adj[i]-1)

current_time = 1;

for i in range(V):
    if visited[i] == True:
        continue
    visited[i] = True
    dfs(i)

for i in range(V):
    print("%d %d %d"%(i+1,go_time[i],back_time[i]))

Submission status: Accepted

Solution code:
import sys
import math
import string
import fractions
import random
from operator import itemgetter
import itertools
from collections import deque
import copy
import heapq
import bisect

MOD = 10 ** 9 + 7
INF = float('inf')
input = lambda: sys.stdin.readline().strip()

sys.setrecursionlimit(10 ** 8)

n = int(input())
info = [list(map(int, input().split())) for _ in range(n)]
ans = [[i + 1, -1, -1] for i in range(n)]
check = [0 for _ in range(n)]
time = 1


def dfs(num):
    check[num] = 1
    global time
    if ans[num][1] == -1:
        ans[num][1] = time
        time += 1
    for i in info[num][2:]:
        if check[i - 1] == 0:
            dfs(i - 1)
    if ans[num][2] == -1:
        ans[num][2] = time
        time += 1


for i in range(n):
    if check[i] == 0:
        dfs(i)

for i in ans:
    i = list(map(str, i))
    print(" ".join(i))

Submission status: Accepted

Solution code:
import sys
# sys.stdin = open('input.txt')

def fillMatrix():
    for i in range(n):
        u, k, *v = map(int, input().split())
        for j in v:
            matrix[i][j-1] = 1

def dfs(u):
    global time
    status[u] = VISITING
    time += 1
    discoverTime[u] = time
    for v in range(n):
        if matrix[u][v] and status[v] == NOT_VISITED:
            dfs(v)
    status[u] = VISITED
    time += 1
    finishTime[u] = time


n = int(input())
matrix = [[0]*n for i in range(n)]
time = 0
discoverTime = [0] * n
finishTime = [0] * n

NOT_VISITED = 0 # WHITE
VISITING = 1 # GRAY
VISITED = 2 # BLACK
status = [NOT_VISITED] * n

fillMatrix()
# Calling dfs(0) alone cannot reach nodes not connected from 0
for i in range(n):
    if status[i] != VISITED:
        dfs(i)

for i in range(n):
    ans = []
    ans.append(i+1)
    ans.append(discoverTime[i])
    ans.append(finishTime[i])
    ans = map(str, ans)
    print(' '.join(ans))

Submission status: Accepted

Solution code:
from collections import deque
n = int(input())
graph = [deque([]) for _ in range(n+1)]
ans = [[i, ] for i in range(n+1)]
for i in range(n):
  u, k, *v = list(map(int, input().split()))
  for j in v:
    graph[u].append(j)
stack = deque()
stack.append(1)
marked = []
t = 0
def dfs(v):
  global t
  marked.append(v)
  t += 1
  ans[v].append(t)
  for i in graph[v]:
    if i in marked:
      continue
    else:
      marked.append(i)
      dfs(i)
  t += 1
  ans[v].append(t)
for i in range(1, n+1):
  if len(ans[i])==1:
    dfs(i)
for i, x in enumerate(ans):
  if i==0:
    continue
  print(*x)

Submission status: Accepted

Solution code:
n = int(input())

points = []
seen = []
find_time = []
end_time = []
for _ in range(n):
    input_text = list(map(int, input().split()))
    u, k, v_list = input_text[0], input_text[1], input_text[2:]
    seen.append(False)
    points.append(v_list)
    find_time.append(0)
    end_time.append(0)

count = [0]


def dfs(graph, v, count):
    seen[v] = True
    find_time[v] = count[0]
    for next_v in graph[v]:
        if seen[next_v - 1]:
            continue
        count[0] += 1
        dfs(graph, next_v - 1, count)
    count[0] += 1
    end_time[v] = count[0]


for index, seen_point in enumerate(seen):
    if seen_point:
        pass
    else:
        count[0] += 1
        dfs(points, index, count)
# print(find_time)
# print(end_time)


count = 1
for f, e in zip(find_time, end_time):
    print(count, f, e)
    count += 1

Submission status: Accepted

Solution code:
import sys
input = lambda: sys.stdin.readline().rstrip()
n=int(input())
s=0 ; st=set() ; ans=[[] for i in range(n)] ; v=0
def dfs(g,v):
    global s,st,ans
    if v in st: return
    else: st.add(v)
    s+=1
    ans[v].append(s)
    for i in g[v]:
        dfs(g,i)
    s+=1
    ans[v].append(s)
g=[]
for _ in range(n):
    a=[int(i)-1 for i in input().split()]
    if a[1]==-1: g.append([])
    else: g.append(a[2:])
for i in range(n):
    if i in st : continue
    else : dfs(g,i)
for i in range(len(ans)):
    print(i+1,*ans[i])

Submission status: Accepted

Solution code:
import sys
sys.setrecursionlimit(2000000)

n = int(input())
m = [list(map(int, input().split()))[2:] for _ in range(n)]

def dfs(x, time):
    first[x] = time
    time += 1
    for v in m[x]:
        if first[v-1] == 0:
            time = dfs(v-1, time)
    finish[x] = time
    time += 1
    return time

first = [0] * n
finish = [0] * n

time = 1
for i in range(n):
    if first[i] == 0:
        time = dfs(i, time)

for i, xy in enumerate(zip(first, finish)):
    print(i+1, *xy)

Submission status: Accepted

Solution code:
# =============================================================================
#　Depth First Search
# =============================================================================
import sys
sys.setrecursionlimit(10**8)

N=int(input())
Graph=[list(map(int,input().split()))[2:] for _ in range(N)]
Graph.insert(0,[])
seen=[False for _ in range(N+1)]
first_order=[0]*(N+1)
last_order=[0]*(N+1)
time=1

def dfs(Graph,v):
    global seen
    global time
    seen[v]=True
    first_order[v]=time
    time+=1
    for nv in Graph[v]:
        if seen[nv]:
            continue
        dfs(Graph,nv)

    last_order[v]=time
    time+=1

for v in range(1,N+1):
    if not seen[v]:
        dfs(Graph,v)
for i in range(1,N+1):
    print(i,first_order[i],last_order[i])

Submission status: Accepted

Solution code:
#!usr/bin/env python3
from collections import defaultdict,deque
from heapq import heappush, heappop
from itertools import permutations
import sys
import math
import bisect
def LI(): return [int(x) for x in sys.stdin.readline().split()]
def I(): return int(sys.stdin.readline())
def LS():return [list(x) for x in sys.stdin.readline().split()]
def S():
    res = list(sys.stdin.readline())
    if res[-1] == "\n":
        return res[:-1]
    return res
def IR(n):
    return [I() for i in range(n)]
def LIR(n):
    return [LI() for i in range(n)]
def SR(n):
    return [S() for i in range(n)]
def LSR(n):
    return [LS() for i in range(n)]

sys.setrecursionlimit(1000000)
mod = 1000000007

cnt = 1
def solve():
    global cnt
    def dfs(x):
        global cnt
        f[x] = cnt
        for y in v[x]:
            if not d[y]:
                d[y] = cnt
                cnt += 1
                dfs(y)
        f[x] = cnt
        cnt += 1

    n = I()
    v = []
    for i in range(n):
        e = LI()
        u = e[2:]
        for i in range(len(u)):
            u[i] -= 1
        v.append(u)
    d = [0]*n
    f = [0]*n
    for i in range(n):
        if not d[i]:
            d[i] = cnt
            cnt += 1
            dfs(i)
    for i in range(n):
        print(i+1,d[i],f[i])
    return

#Solve
if __name__ == "__main__":
    solve()

Submission status: Accepted

Solution code:
n = int(input())
V = [[] for _ in range(n)]
for i in range(n):
    data = list(map(int, input().split(" ")))
    V[i] = data[2:]

answer = [[None, None] for _ in range(n)]

counter = 1


def dfs(v):
    global counter
    if answer[v][0] == None:
        answer[v][0] = counter
        counter += 1
        # ノードの子供の管理
        for e in V[v]:
            dfs(e-1)
        answer[v][1] = counter
        counter += 1


for i in range(len(answer)):
    if answer[i][0] == None:
        dfs(i)

for i in range(len(answer)):
    print(str(i+1) + " " + " ".join(map(str, answer[i])))

Submission status: Accepted

Solution code:
def dfs(v, k):
    if ans[v][1] == 0:
        ans[v][1] = k
    else:
        return k - 1
    for i in d[v]:
        k = dfs(i, k + 1)
    k += 1
    if ans[v][2] == 0:
        ans[v][2] = k
    return k


G = int(input())
vlst = [list(map(int, input().split())) for _ in range(G)]
d = [[] for _ in range(G)]
for i in range(G):
    for j in range(vlst[i][1]):
        d[i].append(vlst[i][2 + j] - 1)
ans = [[_, 0, 0] for _ in range(G)]
k = 1
for i in range(G):
    k = dfs(i, k) + 1
for i in ans:
    print(i[0] + 1, i[1], i[2])

Submission status: Accepted

Solution code:
n = int(input())
d = [0]*(n+1)
f = [0]*(n+1)
t = 1

adjacent_list = [[] for _ in range(n+1)]
for i in range(n):
    e = list(map(int,input().split()))
    if e[1] != 0:
        adjacent_list[i+1].extend(e[2:])
#print(adjacent_list)

def dfs(v):
    if d[v] >= 1:
        return

    global t
    if d[v] == 0: #未発見なら発見時刻を記入
        d[v] = t
    t += 1

    for nv in adjacent_list[v]:
        dfs(nv)
    f[v] = t
    t += 1

for v in range(1,n+1):
    dfs(v)

#dfs(1)
#print(d)
#print(f)
for i in range(1,n+1):
    print(i, d[i], f[i])

Submission status: Accepted

Solution code:
def depth_search(i, adj, d, f, t):
    if d[i-1]:
        return t
    d[i-1] = t
    t += 1                                          
    for v in adj[i-1]:
        t = depth_search(v, adj, d, f, t)
    f[i-1] = t                                      
    t += 1
    return t

n = int(input())
adj = [list(map(int, input().split()))[2:] for _ in range(n)] 

d = [0] * n
f = [0] * n

t = 1
for i in range(n):
    if d[i] == 0:
        t = depth_search(i+1, adj, d, f, t)

for i, df in enumerate(zip(d, f)):
    print(i + 1, *df)

Submission status: Accepted

Solution code:
from collections import deque
import sys
input = sys.stdin.readline


N = int(input())
G = [[] for _ in range(N)]
for _ in range(N):
    ls = list(map(int, input().split()))
    u = ls[0] - 1
    for v in ls[2:]:
        G[u].append(v - 1)

time = 1
d = [None for _ in range(N)]
f = [None for _ in range(N)]

def dfs(v):
    global time
    d[v] = time
    time += 1
    
    for u in range(N):
        if u in G[v]:
            if d[u] is None:
                dfs(u)

    f[v] = time
    time += 1

for v in range(N):
    if d[v] is None:
        dfs(v)

for v in range(N):
    print("{} {} {}".format(v + 1, d[v], f[v]))

Submission status: Accepted

Solution code:
if __name__ == '__main__':
    from sys import stdin
    input = stdin.readline

    N = 100
    WHITE = 0
    GRAY = 1
    BLACK = 2

    M = [[0]*N for _ in range(N)]
    color = [WHITE]*N  # colorの初期化は最初に行っておく。
    d = [0]*N
    f = [0]*N

    def dfs_visit(u):
        global tt
        color[u] = GRAY
        tt += 1
        d[u] = tt # 最初の訪問
        for v in range(n):
            if M[u][v] == 0:
                continue
            if color[v] == WHITE:
                dfs_visit(v)
        color[u] = BLACK
        tt += 1
        f[u] = tt # 訪問の完了

    def dfs():
        global tt
        tt = 0

        for u in range(n):
            if color[u] == WHITE:
                # 未訪問のuを始点として深さ優先探索
                dfs_visit(u)
        for u in range(n):
            print(str(u+1) + ' ' + str(d[u]) + ' ' + str(f[u]))

    n = int(input())
    for _ in range(n):
        u, k, *vv = input().split()
        u = int(u)-1  # 0オリジンにする
        k = int(k)    # kは使わない
        for v in vv:
            v = int(v)-1
            M[u][v] = 1
    dfs()

Submission status: Accepted

Solution code:
def main():
    """有向グラフの深さ優先探索
    
    Note: V[i]は頂点iから通じる頂点の集合を意味するが, 
             V[i]: {i}とV[i]: Noneは同値とされている。
    """
    stack = []
    passed_lines = []
    
    n = int(input())
    V = [None]*(n+1)
    D = [None]*(n+1)
    F = [None]*(n+1)
    passed_vertices = set()
    vertices = set(range(1, n+1))
    
    for i in range(1, n+1):
        _, _, *v = map(int, input().split())
        V[i] = set(v)

    i = 1
    time = 1
    stack.append(i)
    passed_vertices.add(i)
    D[i] = time
    while i <= n:
        new_vertices = list(V[i] - passed_vertices - {i})
        new_vertices.sort()
        if new_vertices:
            i = new_vertices[0]
            stack.append(i)
            time += 1
            if D[i] is None:
                D[i] = time
                passed_vertices.add(i)
            continue
        else:
            while stack:
                i = stack.pop()
                time += 1
                if list(V[i] - passed_vertices - {i}):
                    stack.append(i)
                    time -= 1
                    break
                if F[i] is None: 
                    F[i] = time
        if not list(V[i] - passed_vertices - {i}) and not stack:
            rest_vertices = list(vertices-passed_vertices)
            if rest_vertices:
                i = min(rest_vertices)
                stack.append(i)
                time += 1
                if D[i] is None:
                    D[i] = time
                    passed_vertices.add(i)
            else:
                break
    for id, d, f in zip(range(1, n+1), D[1:], F[1:]):
        print("{} {} {}".format(id, d, f))
        
if __name__ == "__main__":
    main()

Submission status: Accepted

Solution code:
n = int(input())
graph = {}
for _ in range(n):
  i = list(map(int,input().split()))
  graph[i[0]] = i[2:]

first = {i:0 for i in range(1,n+1)}
last = {i:0 for i in range(1,n+1)}
seen = set()
time = 1

def dfs(v):
  global time
  seen.add(v)
  first[v] = time
  time += 1
  for nxt in graph[v]:
    if nxt in seen:
      continue
    dfs(nxt)
  last[v] = time
  time += 1

for i in range(1,n+1):
  if i not in seen:
    dfs(i)
  
for i in range(1,n+1):
  print(i, first[i], last[i])

Submission status: Accepted

Solution code:
N = int(input())
adj_list = []
for _ in range(N):
    line = list(input().split(" "))
    adj_list.append([int(k) - 1 for k in line[2:]])

d = [-1 for _ in range(N)]
f = [-1 for _ in range(N)]
time = 1

visited = set()

def dfs(p):
    global time
    if p in visited:
        return

    d[p] = time
    time += 1
    visited.add(p)
    for ad in adj_list[p]:
        if ad not in visited:
            dfs(ad)
    f[p] = time
    time += 1

for i in range(N):
    dfs(i)

for i in range(N):
    print(f"{i + 1} {d[i]} {f[i]}")

Submission status: Accepted

Solution code:
import sys
input = sys.stdin.readline
d = []
f = []
time = 0
def search(r):
    global d,f,time,s
    if d[r] == 0:
        time += 1
        d[r] = time
    else:
        return
    for x in s[r]:
        search(x)
    time += 1
    f[r] = time


n = int(input())
s = [[] for i in range(n+1)]
for _ in range(n):
    d = list(map(int,input().split()))
    s[d[0]] = d[2:]

d = [0 for _ in range(n+1)]
f = [0 for _ in range(n+1)]

for i in range(1,n+1):
    if d[i] == 0:
        search(i)

for i in range(1,n+1):
    print (i,d[i],f[i])

Submission status: Accepted

Solution code:
#!/usr/bin/env python3

import sys
import math
from bisect import bisect_right as br
from bisect import bisect_left as bl
sys.setrecursionlimit(2147483647)
from heapq import heappush, heappop,heappushpop
from collections import defaultdict
from itertools import accumulate
from collections import Counter
from collections import deque
from operator import itemgetter
from itertools import permutations
mod = 10**9 + 7
inf = float('inf')
def I(): return int(sys.stdin.readline())
def LI(): return list(map(int,sys.stdin.readline().split()))

cnt = 1
def dfs(x):
    global cnt
    if s[x] == None:
        s[x] = cnt
        cnt += 1
    for v in edges[x]:
        if s[v] == None:
            dfs(v)
    g[x] = cnt
    cnt += 1
    return 

n = I()
edges = [[] for _ in range(n)]
for i in range(n):
    edges[i] = list(map(lambda x:x-1,LI()[2:]))

s = [None]*n
g = [None]*n
for i in range(n):
    if s[i] == None:
        dfs(i)
for i in range(n):
    print(i+1,s[i],g[i])