【第二届全国高校绿色计算大赛 预赛第二阶段(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
'''
posted @ 2020-08-25 20:43  Valk3  阅读(165)  评论(0编辑  收藏  举报