看见题目知道时间复杂度不超过(mlogm)。
这题用强连通分量 Tarjan 算法,强联通:对于任意两个点u和v,u可以到达v,v也可以到达u。这题需要考虑有重边,自环,同样别忘记可能会有两个点u和v,u不能到达v,v也不能到达u的情况,就是u和v不在同一个图中,数据中会存在几个图的情况。
Tarjan 算法主要是维护两个列表dnf和low,dnf[i]记录到达i这个点的次序,low记录i这个点的祖先次序。如果dnf[i]==low[i],就是说i这个点就是祖先节点,如果dnf[i] != low[i],那么i这个点是某个祖先节点的儿子。
洛谷超时一个,还有待改进。
遇到一个问题就是,需要考虑数据中存在不同的图!!!!
from collections import defaultdict, deque
def taij(node):
global idx
dfn[node] = idx
low[node] = idx
idx += 1
stack.append(node)
v[node] = 1
vis[node] = 1
for nex in edge[node]:
if vis[nex] == 0:
taij(nex)
low[node] = min(low[node], low[nex])
elif v[nex]:
low[node] = min(low[node], dfn[nex])
if dfn[node] == low[node]:
ls = []
while dfn[stack[-1]] != dfn[node]:
nex = stack.pop()
ls.append(nex+1)
v[nex] = 0
nex = stack.pop()
v[nex] = 0
ls.append(nex+1)
ls = sorted(ls[::-1])
ans.append(ls)
n, m = map(int, input().split())
edge = defaultdict(list)
dfn = [0]*n
low = [0]*n
stack = deque()
v = [0]*n
vis = [0]*n
idx = 0
ans = []
for _ in range(m):
uu, vv = map(int, input().split())
edge[uu-1].append(vv-1)
taij(0)
for i in range(n):
if vis[i] == 0:
taij(i)
leth = len(ans)
print(leth)
ans.sort()
for i in range(leth):
for j in ans[i]:
print(j, end=' ')
print()