CSP-Week6 ProblemC kruskal最小生成树+超级源点(Gym - 270437H)

本文详细介绍了CSP中Kruskal算法构造最小生成树的思想,包括算法的实现步骤、性质证明以及如何用超级源点解决特殊情况。通过实例分析了如何在图中寻找最小生成树,同时给出了使用C++实现的代码。
摘要由CSDN通过智能技术生成

CSP-kruskal生成树+超级源点思想

相关知识简述

最小生成树是图论涉及连通类题目中重要的一个组成部分,其生成算法主要有kruskal和prim两种。考虑到prim的实现需要使用斐波那契堆优化或平衡树优化,实现困难较大,这里我们只叙述kruskal实现方法和思路。
kruskal的算法核心思想只有一句
“贪心地选出最短边,不成环则加入边集,否则跳过”
为了方便具体的实现,我们将算法细节展开:
1、对所有边按照边权排序
2、按照顺序访问每条边,如果与已有的边不形成环就选择,否则跳过
3、如果合法选择了n-1条边,说明图已经连通,最小生成树生成成功;如果访问过所有边,边数仍然小于n-1,说明图不连通
最小生成树重要性质: 最小生成树也是最小瓶颈生成树(选取边的最大值最小)
关于最小瓶颈生成树证明:
采用反证法:最小生成树最大边a边集为A,最小瓶颈生成树最大边b边集为B,且a>b
可以分成两种情况证伪:
情况一:b∈A
由于SIZE(A)=SIZE(B),B中一定存在边c,且c∉A。说明该边在最小生成树生成过程中被跳过,一旦加入形成环路。因此B非树,与假设相悖。
情况二:b∉A
由于b<a,说明在最小生成树在生成过程中,将b跳过,如果将b加入会形成环路,因此B非树,与假设相悖
由此可以证明:最小生成树也是最小瓶颈生成树。
该性质可以用于:在图中求解生成树,且要求满足所选边的最大值最小。根据性质,可以直接求解一遍最小生成树,记录最小生成树的最大边即可完成。
kruskal最小生成树实现
纵观kruskal的三个步骤,第一步可以直接sort解决,第三步可以通过一个特判完成,最大的求解困难就是第二步了。对于环路的形成判定,如果每次添加边都通过SPFA的方式判定,可能需要浪费掉很多时间。
我们可以转换一下思维,不去判断是否成环,而是判断加边的两个端点是否在同一个连通分支上。如果两个端点在同一个连通分支上,加入这条边一定会导致成环。虽然环的位置未知,但是在生成树问题中成环的位置并不重要,我们只需要知道边的加入是否会导致成环。
分析到这里,一切已经迎刃而解,连通分支可以用并查集完美解决。具体实现见文末源码。

题目概述

东东在老家农村无聊,想种田。农田有 n 块,编号从 1~n。种田要灌氵
众所周知东东是一个魔法师,他可以消耗一定的 MP 在一块田上施展魔法,使得黄河之水天上来。他也可以消耗一定的 MP 在两块田的渠上建立传送门,使得这块田引用那块有水的田的水。 (1<=n<=3e2)
黄河之水天上来的消耗是 Wi,i 是农田编号 (1<=Wi<=1e5)
建立传送门的消耗是 Pij,i、j 是农田编号 (1<= Pij <=1e5, Pij = Pji, Pii =0)
东东为所有的田灌氵的最小消耗

INPUT&输入样例

第1行:一个数n
第2行到第n+1行:数wi
第n+2行到第2n+1行:矩阵即pij矩阵
输入样例

4
5
4
4
3
0 2 2 2
2 0 3 3
2 3 0 4
2 3 4 0

OUTPUT&输出样例

东东最小消耗的MP值
输出样例

9

题目重述

图上的每个点有两种方式能够连接到:
1、已经连通的分支有边能够到达该点,消耗m大小的MP
2、使用创造水源,成为一个水源点,消耗n大小的MP
要将所有点连通,且使用最少的MP

思路概述

如果将创造水源的条件去掉,显而易见这是一道最小生成树问题,但是由于每个点可以创造水源而使自己连通,因此使用传统的最小生成树无法解决该问题。
但是不要轻易地直接否定想法,或许在原想法上加一些新的思考就可以得到正解。
由于每个点都可以引入水源,且引入的耗费不相同,我们可以引入超级源点(0号点)。只需要在原图中增添超级源点到其他点的耗费–等于在该点引入水源的耗费。接下来只需要进行最小生成树就可以完成需求了。
我们可以模拟下算法的工作流程:
将所有边(包括超级源点的水源边)进行排序。
每次贪心地选择最短边,如果成环就跳过。在这个过程中,即使某些点原图中是无法通过连通分支抵达的,但是由于超级源点的存在,该点可以从选择连向超级源点的水源边,从而完成n-1条边的选取。
由于超级源点到所有点都存在一条边,所以可以保证一定能够选出n-1条边,完成生成树的建立。

题目源码

#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值