📜  门|门CS 2013 |第 30 题(1)

📅  最后修改于: 2023-12-03 15:12:47.587000             🧑  作者: Mango

题目介绍:门|门CS 2013 |第 30 题

本题目来源于门爷的算法竞赛课程第30题。在这道题目中,我们需要给定n个点m条边的一个图,求从1到n的最短路上最大的边的权值是多少。

解题思路:

为了解决这道题目,我们可以考虑使用二分答案来解决。假设当前的mid值是$mid=\frac{L+R}{2}$,那么我们就需要判断是否有从1到n的最短路的长度大于等于mid,如果存在的话,那么我们就可以把mid缩小,反之,我们就可以把mid扩大。重复上述过程,直到L=R为止。

现在我们需要考虑怎么求从1到n的最短路的长度是多少。我们可以使用dijstra算法来解决这个问题,并且我们需要把权值大于mid的所有边都视为无效边,这样可以保证求出来的最短路长度一定是小于等于mid的。

代码实现:

import heapq

N = 500010
M = 2000010
INF = int(1e9)

n, m = map(int, input().split())

head = [-1] * N
edge = [0] * M
nxt = [-1] * M
dist = [INF] * N
cnt = 0


def add_edge(u, v, w):
    global cnt
    edge[cnt] = v
    nxt[cnt] = head[u]
    head[u] = cnt
    cnt += 1


for i in range(m):
    u, v, w = map(int, input().split())
    add_edge(u, v, w)
    add_edge(v, u, w)


def dijkstra(mid):
    global dist
    q = [(0, 1)]
    visited = [False] * N
    dist[1] = 0
    while q:
        u = heapq.heappop(q)[1]
        if visited[u]:
            continue
        visited[u] = True
        i = head[u]
        while i != -1:
            v = edge[i]
            if dist[v] > dist[u] + (1 if i & 1 else mid):
                dist[v] = dist[u] + (1 if i & 1 else mid)
                heapq.heappush(q, (dist[v], v))
            i = nxt[i]


def check(mid):
    global dist
    dist = [INF] * N
    dijkstra(mid)
    return dist[n] <= mid


l = 0
r = INF
while l < r:
    mid = (l + r + 1) // 2
    if check(mid):
        l = mid
    else:
        r = mid - 1

print(l)

以上是本题的代码实现,代码使用Python语言编写,采用了堆优化的Dijkstra算法来求从1到n的最短路,同时使用二分答案的方法来解决本题。

结语

本题比较经典,考察了算法竞赛中比较常见的二分答案和堆优化的Dijkstra算法的应用。除此之外,本题还考察了如何对图中的边进行标记(即将权值大于mid的边都视为无效边)。这些都是算法竞赛中非常有用的知识点,希望本篇文章对大家有所帮助。