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