【第二届全国高校绿色计算大赛 预赛第二阶段(Python)】Tarjan + 最短路
运输成本
题意
给出一个有向图,如果两个城市之间可以互相到达,那么他们就是一个联邦,对于同一个联邦的两个城市,他们之间运输成本为 0 ,现在让求出整个图中的最长路。
思路
首先跑 Tarjan 缩点,然后建立一个超级源点,他到所有点的距离为 0,然后跑最长路。
Python 版的 Dijkstra + 优先队列
代码
'''
Autor: valk
Date: 2020-08-19 18:23:25
LastEditTime: 2020-08-19 22:07:06
Description: 如果邪恶 是华丽残酷的乐章 它的终场 我会亲手写上 晨曦的光 风干最后一行忧伤 黑色的墨 染上安详
'''
import heapq
class Edge:
u, v, w = None, None, None
def __init__(self, u, v, w):
self.u = u
self.v = v
self.w = w
class Solver:
def solve(self, n, edges):
N = 200010
inf = 10 ** 9
edge = [[] for i in range(N)]
edge2 = [[] for i in range(N)]
cnt = 0
top = 0
num = 0
dfn = [0 for i in range(N)]
low = [0 for i in range(N)]
Stack = [0 for i in range(N)]
vis = [0 for i in range(N)]
fa = [0 for i in range(N)]
dis = [0 for i in range(N)]
def tarjan(u):
nonlocal cnt,dfn,low,vis,num,top,fa,edge,Stack
cnt+=1
dfn[u] = low[u] = cnt
top+=1
Stack[top] = u
vis[u] = 1
for pair in edge[u]:
v = pair[0]
if dfn[v] == 0:
tarjan(v)
if low[v] < low[u]:
low[u] = low[v]
elif (vis[v]):
if low[u] > dfn[v]:
low[u] = dfn[v]
if low[u] == dfn[u]:
v = 0
num += 1
v = Stack[top]
top -= 1
vis[v] = 0
fa[v] = num
while (u != v):
v = Stack[top]
top -= 1
vis[v] = 0
fa[v] = num
def dijkstra(u, n):
nonlocal vis, dis, edge2
for i in range(1, n+1):
vis[i] = 0
dis[i] = inf
dis[u] = 0
q = []
heapq.heappush(q, (dis[u], u))
while (len(q) > 0):
pair = heapq.heappop(q)
now = pair[1]
for node in edge2[now]:
to = node[0]
w = node[1]
if dis[to] > dis[now] + w:
dis[to] = dis[now] + w
heapq.heappush(q, (dis[to], to))
for i in edges:#print
edge[i.u].append((i.v, i.w))
for i in range(1, n + 1):
if (dfn[i] == 0):
tarjan(i)
for i in range(1, n + 1):
u=fa[i]
for node in edge[i]:
if u == fa[node[0]]:
continue
edge2[u].append((fa[node[0]], -node[1]))
for i in range(1, num + 1):
edge2[num + 1].append((i, 0))
dijkstra(num + 1, num + 1)
ans = inf
for i in range(1, num + 2):
if dis[i] < ans:
ans = dis[i]
return -ans
'''
5
1 2 1
2 3 1
3 4 1
4 2 1
4 5 1
0 0 0
'''