1. 程式人生 > 實用技巧 >【第二屆全國高校綠色計算大賽 預賽第二階段(Python)】Tarjan + 最短路

【第二屆全國高校綠色計算大賽 預賽第二階段(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
'''