P2820 局域网 Python题解

局域网

题目背景

某个局域网内有 n n n 台计算机,由于搭建局域网时工作人员的疏忽,现在局域网内的连接形成了回路,我们知道如果局域网形成回路那么数据将不停的在回路内传输,造成网络卡的现象。因为连接计算机的网线本身不同,所以有一些连线不是很畅通,我们用 f ( i , j ) f(i,j) f(i,j) 表示 i , j i,j i,j 之间连接的畅通程度, f ( i , j ) f(i,j) f(i,j) 值越小表示 i , j i,j i,j 之间连接越通畅, f ( i , j ) f(i,j) f(i,j) 0 0 0 表示 i , j i,j i,j 之间无网线连接。

题目描述

现在需要解决回路问题,我们将除去一些连线,使得网络中没有回路,不改变原图节点的连通性,并且被除去网线的 ∑ f ( i , j ) \sum f(i,j) f(i,j) 最大,请求出这个最大值。

输入格式

第一行两个正整数 n , k n,k n,k

接下来的 k k k 行每行三个正整数 i , j , m i,j,m i,j,m 表示 i , j i,j i,j 两台计算机之间有网线联通,通畅程度为 m m m

输出格式

一个正整数, ∑ f ( i , j ) \sum f(i,j) f(i,j) 的最大值。

样例 #1

样例输入 #1

5 5
1 2 8
1 3 1
1 5 3
2 4 5
3 4 2

样例输出 #1

8

提示

对于全部数据,保证 1 ≤ n ≤ 100 1\le n \le 100 1n100 1 ≤ f ( i , j ) ≤ 1000 1\le f(i,j)\le 1000 1f(i,j)1000

题解

首先明确一些信息:

  1. 这是一个无向图(我一开始当成有向图来做了)
  2. 这题是一个求最小生成树的题目
  3. 这题的目标不是求最小生成树,而是最小生成树的总权值(尽管它说的是删除掉的边的权值和,但是求出最小生成树的权值,删除掉的也就出来了)
  4. 这题有可能有多个连通分量,每个连通分量的最小生成树的总权值都要求一次

最小生成树算法主要有以下几种:
无权图(权值全一样的图):BFS、Prim、Kruskal
有权图:Prim、Kruskal

其中Kruskal算法涉及并查集数据结构,我不太懂并查集实现,所以这道题我就使用了Prim算法,因为不需要我们真的去还原最小生成树,当然,想还原也不难。

既然不需要还原,我们只需要知道,Prim算法每次从优先队列中取出一条边,这条边指向的节点只要没被访问过,那么我们就可以把这条边的权值加在最小生成树的总权值中。

代码:
注意一些地方,因为Python的heapq不能指定对元组的第几位进行排序,只能针对元组的第一位进行堆排序,所以我这里设计的图会有点怪。

import heapq
import copy
def myPrim(graph, startnode):
    global N, K, ans, visited
    if visited[startnode] == 1:
        return
    visited[startnode] = 1
    priority_queue = copy.deepcopy(graph[startnode])
    heapq.heapify(priority_queue)
    while priority_queue:
        node = heapq.heappop(priority_queue)
        if visited[node[1]] == 0:
            ans += node[0]
            visited[node[1]] = 1
        else:
            continue
        for neighbor in graph[node[1]]:
            if visited[neighbor[1]] != 1:
                heapq.heappush(priority_queue, neighbor)



N, K = map(int, input().strip().split())
graph = {i+1: [] for i in range(N)}
totalweight, ans = 0, 0
for i in range(K):
    val = list(map(int, input().strip().split()))
    graph[val[0]].append((val[2], val[1], val[0]))
    graph[val[1]].append((val[2], val[0], val[1]))
    totalweight += val[2]

visited = [0 for _ in range(N+1)]
for i in range(1, N+1):
    myPrim(graph, i)
print(totalweight-ans)

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值