📜  门| GATE CS 2021 |设置 1 |问题 18(1)

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

门| GATE CS 2021 |设置 1 |问题 18

本文介绍 GATE CS 2021 设置 1 的问题 18,其中涉及到一些图论和算法的知识。该题目中提到了一个有向图和找到特定路径的问题,下面将进行详细介绍。

题目描述

给定一个有向无环图 (DAG),该图由 n 个节点和 m 条有向边组成。每个节点都有一个数字编号,编号从 1 到 n。现在,你需要找到两个节点 x 和 y,使得连接它们的路径上的边权与其他任何路径的边权总和之比最大。请注意,路径可以从 x 到 y 或从 y 到 x。

输入格式: 第一行包含两个整数 n 和 m。 以下 m 行每行包含三个整数 x、y 和 w,表示从节点 x 到节点 y 有一条边,边的权重为 w。

输出格式: 输出一个实数,为连接 x 和 y 的路径上的边权与其他任何路径的边权总和之比的最大值,保留 2 位小数。

解题思路

由于给出的是一个 DAG,因此可以考虑使用动态规划求解最短路径问题。具体而言,我们需要使用数组 dist 来记录从起点到各个点的最短距离。在这个问题中我们需要求解的是两个节点之间的最短路径,因此可以使用 Floyd 算法求解任意两点之间的最短路径。

在求得任意两点之间的最短路径之后,我们需要考虑如何找到连接 x 和 y 的路径。为此,我们可以使用 Dijkstra 算法从 x 和 y 分别向外扩展,直到它们相遇。具体而言,我们可以使用两个堆,一个堆用于从 x 开始到达的节点,另一个堆用于从 y 开始到达的节点。

代码实现
INF = 100000000
n, m = map(int, input().split())
graph = [[INF] * n for _ in range(n)]
for i in range(m):
    x, y, w = map(int, input().split())
    graph[x-1][y-1] = w

# Floyd算法求任意两点之间的最短路径
for k in range(n):
    for i in range(n):
        for j in range(n):
            graph[i][j] = min(graph[i][j], graph[i][k] + graph[k][j])

# 初始化堆
import heapq
def get_heap(data, start):
    heap = []
    heapq.heappush(heap, (0, start))
    dist = [INF] * n
    dist[start] = 0
    while heap:
        d, node = heapq.heappop(heap)
        if d > dist[node]:
            continue
        for i in range(n):
            if dist[i] > dist[node] + data[node][i]:
                dist[i] = dist[node] + data[node][i]
                heapq.heappush(heap, (dist[i], i))
    return dist

# 从x和y分别向外扩展,直到他们相遇
x, y = map(int, input().split())
x -= 1
y -= 1
heap_x = get_heap(graph, x)
heap_y = get_heap(graph, y)
# 求解最大比例
max_ratio = 0
for i in range(n):
    for j in range(i+1, n):
        if heap_x[i] + graph[i][j] + heap_y[j] == heap_x[y] and heap_y[j] + graph[j][i] + heap_x[i] == heap_y[x]:
            if graph[i][j] == INF:
                continue
            ratio = graph[i][j] / max(heap_x[i] + heap_y[j], heap_x[j] + heap_y[i])
            max_ratio = max(max_ratio, ratio)
print("%.2f"%max_ratio)

在这段代码中,我们首先使用 Floyd 算法求解任意两点之间的最短路径,并将计算结果保存在 graph 中。随后,我们使用 Dijkstra 算法分别从 x 和 y 向外扩展,得到从 x 和 y 到各个点的最短距离。最后,我们枚举每一组 i 和 j,检查它们是否满足 x 到 i 到 j 到 y 和 y 到 j 到 i 到 x 两条路径的条件,如果满足的话就计算它们之间的路径比例,并更新最大比例。最后输出最大比例即可。