📜  门|门CS 2008 |第 70 题(1)

📅  最后修改于: 2023-12-03 14:58:36.778000             🧑  作者: Mango

题目描述

在一个城市中有许多房屋和许多道路相连,城市可以表示成一个n个点m条边的无向图,假设每条道路i的长度为Li,犯罪率为Pi,现在需要修建一条新的路(就是在原有的基础上增加一条边),使得整个城市中Li*Pi之和最小,求最小值。

输入格式

第1行:2个整数,分别表示城市的点数n和道路数m

第2~m+1行:每行三个整数,分别表示道路的起点、终点和犯罪率Pi

输出格式

输出一行一个浮点数 表示最小Li * Pi之和,四舍五入保留三位小数。

输入样例
5 6
1 2 3
1 3 4
2 3 6
2 4 8
3 4 8
4 5 7
输出样例
27.000
算法思路

该题目可以使用最小生成树算法来解决。首先对给定的边按照犯罪率Pi从小到大进行排序,依次加入每一条边构建一颗树,当新加入的边满足不在同一连通分量中时,将其加入答案中,并将两个连通分量合并。最终,答案即为所求。

代码片段
import sys
from heapq import *


def prim():
    dis = [float("inf")] * (n + 1)
    st = [False] * (n + 1)
    dis[1] = 0
    heap = []
    heappush(heap, (0, 1))
    res = 0
    while heap:
        dist, t = heappop(heap)
        if st[t]:
            continue
        st[t] = True
        res += dist
        for pair in adj[t]:
            if not st[pair[0]] and pair[1] < dis[pair[0]]:
                dis[pair[0]] = pair[1]
                heappush(heap, (dis[pair[0]], pair[0]))
    return res


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

adj = [[] for _ in range(n + 1)]
for _ in range(m):
    a, b, c = map(int, input().split())
    adj[a].append((b, c))
    adj[b].append((a, c))

adj.sort(key=lambda x: x[1])

print("{:.3f}".format(prim()))

注意代码中的变量解释和参数含义。具体请参见代码注释。