deftarjan(x): global cnt # 当前时间戳 cnt += 1 dfn[x] = low[x] = cnt flag = 0# 子树中不满足条件的点的数量 for y,w in g[x]: ifnot dfn[y]: tarjan(y) low[x] = min(low[x], low[y]) # 树边更新low值 if low[y] >= dfn[x]: # 返祖边在x下侧,只要有x就是割点 flag += 1 if (x != root or flag > 1): boo[x] = 1# 如果是root,还要保证儿子数大于1 else: low[x] = min(low[x], dfn[y]) # 非树边更新 low值
n,m = map(int, input().split()) g = [[] for _ inrange(n+1)] for _ inrange(m): x,y = map(int, input().split()) if x == y: continue g[x].append(y) g[y].append(x)
cnt = 0# 用于记录当前时间戳 dfn, boo = [0]*(n+1), [0]*(n+1) # dfn:时间戳, boo:是否为割点 low = [i for i inrange(n+1)] for i inrange(1,n+1): ifnot dfn[i]: root = i tarjan(i)
defadd(x,y,z): global tot tot += 1 ver[tot],edge[tot] = y,z nxt[tot],head[x] = head[x],tot deftarjan(x, in_edge): global cnt # 在solve里面用 nonlocal cnt cnt += 1 dfn[x] = low[x] = cnt i = head[x] while i: y = ver[i] ifnot dfn[y]: tarjan(y,i) low[x] = min(low[x], low[y]) if low[y] > dfn[x]: # (x,y) 为桥 bridge[i] = bridge[i^1] = 1 elif i != (in_edge^1): # 忽略反向边 low[x] = min(low[x],dfn[y]) i = nxt[i] n,m = map(int, input().split()) head = [0]*(n+1) ver,edge,nxt = [0]*(2*m+1),[0]*(2*m+1),[0]*(2*m+1) tot = 0
for i inrange(m): x,y,z = map(int, input().split()) add(x,y,z) add(y,x,z)
bridge = [0]*(2*m+1) dfn,low = [0]*(n+1), [i for i inrange(n+1)] cnt = 0 for i inrange(1,n+1): ifnot dfn[i]:tarjan(i,0) for i inrange(2,tot+1,2): if bridge[i]: print(ver[i^1],ver[i])
deftarjan(x): global cnt,tot # 当前时间戳 cnt += 1 dfn[x] = low[x] = cnt st.append(x) if x == root andlen(g[x]) == 0: tot += 1 dcc[tot].append(x) return flag = 0# 子树中不满足条件的点的数量 for y in g[x]: ifnot dfn[y]: tarjan(y) low[x] = min(low[x], low[y]) # 树边更新low值 if low[y] >= dfn[x]: # 返祖边在x下侧,只要有x就是割点 flag,tot= flag + 1, tot + 1 if (x != root or flag > 1): boo[x] = 1# 如果是root,还要保证儿子数大于1 while st[-1] != x: dcc[tot].append(st.pop()) dcc[tot].append(x) else: low[x] = min(low[x], dfn[y]) # 非树边更新 low值
n,m = map(int, input().split()) g = [[] for _ inrange(n+1)] for _ inrange(m): x,y = map(int, input().split()) if x == y: continue g[x].append(y) g[y].append(x)
"""求v-DCC""" cnt,tot = 0,0# 用于记录当前时间戳, dcc编号 dfn, boo = [0]*(n+1), [0]*(n+1) # dfn:时间戳, boo:是否为割点 low = [i for i inrange(n+1)] st,dcc = [],[[] for i inrange(n+1)] # stack, v-DCC for i inrange(1,n+1): ifnot dfn[i]: root = i tarjan(i)
"""v-DCC 缩点""" cnt = tot new_id = [0]*(n+1) for i inrange(1,n+1): if boo[i]: # 给每个割点一个新的编号(从 cnt+1 开始) cnt += 1 new_id[i] = cnt gg = [[] for _ inrange(cnt + 1)] c = [0]*(n+1) # v-DCC 染色 for i inrange(1,tot+1): for j inrange(len(dcc[i])): x = dcc[i][j] if boo[x]: gg[i].append(new_id[x]) gg[new_id[x]].append(i) else: c[x] = i # 除割点外,其他点仅属于1个 v-DCC
deftarjan(x): global cnt,tot # 当前时间戳 cnt += 1 dfn[x] = low[x] = cnt st.append(x) ins[x] = 1 for y in g[x]: ifnot dfn[y]: tarjan(y) low[x] = min(low[x], low[y]) elif ins[y]: low[x] = min(low[x],dfn[y]) if dfn[x] == low[x]: tot += 1 while st[-1] != x: y = st.pop() ins[y] = 0 c[y] = tot, scc[tot].append(y) y = st.pop() ins[y] = 0 c[y] = tot, scc[tot].append(y) cnt,tot = 0,0# 用于记录当前时间戳, scc编号 n,m = map(int, input().split()) g = [[] for _ inrange(n+1)] for _ inrange(m): x,y = map(int, input().split()) if x == y: continue g[x].append(y) g[y].append(x)
"""求SCC""" dfn,c = [0]*(n+1),[0]*(n+1) # dfn:时间戳, c:SCC编号 low = [i for i inrange(n+1)] scc = [[] for _ inrange(n+1)] st,ins = [],[0]*(n+1) # stack, if in stack or not for i inrange(1,n+1): ifnot dfn[i]: tarjan(i)
"""SCC缩点""" gc = [[] for _ inrange(tot+1)] for x inrange(1,n+1): for y in g[x]: if c[x] == c[y]: continue g[c[x]].append(c[y])