Buggy python submission (verdict: Time Limit Exceeded):
import sys
input = sys.stdin.readline
sys.setrecursionlimit(10**7)

N, M = map(int,input().split())
to = [[] for _ in range(N)]
fr = [[] for _ in range(N)]
for _ in range(N-1+M):
    A, B = map(int,input().split())
    A -= 1
    B -= 1
    to[A].append(B)
    fr[B].append(A)

depth = [-1] * N

def dfs(v, d):
    depth[v] = max(depth[v], d)
    nd = d + 1
    for nv in to[v]:
        dfs(nv, nd)

root = -1
for v in range(N):
    if len(fr[v]) == 0:
        root = v
        break

dfs(root, 0)

vlist = [[] for _ in range(N)]
for v, d in enumerate(depth):
    vlist[d].append(v)

for v in range(N):
    d = depth[v]
    if d == 0:
        print(0)
        continue
    parent = set(vlist[d-1]) & set(fr[v])
    print(parent.pop()+1)

Fixed submission:
import sys
input = sys.stdin.readline
from collections import deque

N, M = map(int,input().split())
to = [[] for _ in range(N)]
fr = [[] for _ in range(N)]
for _ in range(N-1+M):
    A, B = map(int,input().split())
    A -= 1; B -= 1
    to[A].append(B)
    fr[B].append(A)

# トポロジカルソート　計算量O(V+E)
# 有向グラフに用いる
# 閉路検出(DAGの判定)やDPの更新順序を明らかにするときなどに使える

# num[i] : iに入ってくる有効辺の本数
num = [0] * N

# グラフの構築でnumを更新しておく
num = [len(fr[v]) for v in range(N)]

S = deque()
L = []
#　例えば-1で初期化 dp = [-1] * N
'''  編集　'''

for v in range(N):
    if num[v] == 0:
        S.append(v)
        # 入次数0の頂点において例えば0で初期化　dp[v] = 0
        '''　編集　'''

while S:
    v = S.popleft()
    L.append(v)
    for nv in to[v]:
        num[nv] -= 1
        if num[nv] == 0:
            S.append(nv)
        # dpの更新　例えばmaxをとる dp[nv] = max(dp[nv], dp[v] + w[v])
        ''' 　編集 '''

# 閉路がある場合の処理
if len(L) != N:
    '''  編集　'''
    pass

index = [-1] * N
for i, v in enumerate(L):
    index[v] = i

for v in range(N):
    if v == L[0]:
        print(0)
        continue
    pv = -1
    d = N
    for cand in fr[v]:
        res = index[v] - index[cand]
        if res < d:
            d = res
            pv = cand
    pv += 1
    print(pv)

Buggy python submission (verdict: Time Limit Exceeded):
import sys
input = sys.stdin.readline
sys.setrecursionlimit(10**7)

N, M = map(int,input().split())
to = [[] for _ in range(N)]
fr = [[] for _ in range(N)]
for _ in range(N-1+M):
    A, B = map(int,input().split())
    A -= 1
    B -= 1
    to[A].append(B)
    fr[B].append(A)

depth = [-1] * N

def dfs(v, d):
    depth[v] = max(depth[v], d)
    nd = d + 1
    for nv in to[v]:
        dfs(nv, nd)

root = -1
for v in range(N):
    if len(fr[v]) == 0:
        root = v
        break

dfs(root, 0)

vlist = [[] for _ in range(N)]
for v, d in enumerate(depth):
    vlist[d].append(v)

for v in range(N):
    d = depth[v]
    if d == 0:
        print(0)
        continue
    parent = set(vlist[d-1]) & set(fr[v])
    print(parent.pop()+1)


Fixed submission:
import sys
input = sys.stdin.readline
from collections import deque

N, M = map(int,input().split())
to = [[] for _ in range(N)]
fr = [[] for _ in range(N)]
for _ in range(N-1+M):
    A, B = map(int,input().split())
    A -= 1; B -= 1
    to[A].append(B)
    fr[B].append(A)

# トポロジカルソート　計算量O(V+E)
# 有向グラフに用いる
# 閉路検出(DAGの判定)やDPの更新順序を明らかにするときなどに使える

# num[i] : iに入ってくる有効辺の本数
num = [0] * N

# グラフの構築でnumを更新しておく
num = [len(fr[v]) for v in range(N)]

S = deque()
L = []
#　例えば-1で初期化 dp = [-1] * N
'''  編集　'''

for v in range(N):
    if num[v] == 0:
        S.append(v)
        # 入次数0の頂点において例えば0で初期化　dp[v] = 0
        '''　編集　'''

while S:
    v = S.popleft()
    L.append(v)
    for nv in to[v]:
        num[nv] -= 1
        if num[nv] == 0:
            S.append(nv)
        # dpの更新　例えばmaxをとる dp[nv] = max(dp[nv], dp[v] + w[v])
        ''' 　編集 '''

# 閉路がある場合の処理
if len(L) != N:
    '''  編集　'''
    pass

index = [-1] * N
for i, v in enumerate(L):
    index[v] = i

for v in range(N):
    if v == L[0]:
        print(0)
        continue
    pv = -1
    d = N
    for cand in fr[v]:
        res = index[v] - index[cand]
        if res < d:
            d = res
            pv = cand
    pv += 1
    print(pv)