701强连通分量(python)

看见题目知道时间复杂度不超过(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()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值