CCF-201509-4-高速公路

这题很明显是要找强连通分量,找到图中所有的强连通分量,并计算每个分量的城市对数相加得出答案。计算城市对的方法为:强连通分量的结点数 * (强连通分量的结点-1)/ 2

python代码:

import sys

sys.setrecursionlimit(10 ** 7)


def tarjan(u):
    global idx
    global bcnt
    idx += 1
    dfn[u] = low[u] = idx
    stack.append(u)
    in_stack[u] = True

    for v in graph[u]:
        if not dfn[v]:
            tarjan(v)  # dfs(v)
            low[u] = min(low[u], low[v])  # 回溯
        elif in_stack[v]:
            low[u] = min(low[u], dfn[v])

    # 回溯后,判断dfn[u] == low[u],把u以上的点弹出
    if dfn[u] == low[u]:
        sccs[bcnt] = []
        while True:
            v = stack.pop()
            in_stack[v] = False
            sccs[bcnt].append(v)
            if u == v:
                break
        bcnt += 1


n, m = map(int, input().split())
graph = [[] for _ in range(n)]
for i in range(m):
    from_n, to_n = [int(e) - 1 for e in input().split()]
    graph[from_n].append(to_n)

# 结点的时间戳,顺便充当标记数组,0代表未被访问,大于0表示访问过
dfn = [0] * n

# 结点的最小时间
low = [0] * n

# 当前时间
idx = 0

stack = []

# 标记是否在栈中
in_stack = [False] * n

# 强连通分量集
sccs = {}

# 强连通分量数量
bcnt = 0

for i in range(n):
    if not dfn[i]:
        tarjan(i)

ans = 0
for v in sccs.values():
    cnt = len(v)
    ans += int(cnt / 2 * (cnt - 1))
print(ans)

你可能感兴趣的:(CCF)