To_Heart—题解——一本通 3.1 练习4 Tree

题目描述

原题来自:2012 年国家集训队互测

给你一个无向带权连通图,每条边是黑色或白色。让你求一棵最小权的恰好有 条白色边的生成树。题目保证有解。

输入格式

第一行V,E,need 分别表示点数,边数和需要的白色边数。

接下来E行,每行s,t,c,col表示这边的端点(点从0开始标号),边权,颜色(0白色,1黑色)。

输出格式

一行表示所求生成树的边权和。

样例

样例输入

2 2 1
0 1 1 1
0 1 2 0

样例输出

2

题解:

这个题要求在选取特定数量的基础上,构造一棵最小生成树。我们想一下,因为最小生成树所选择的是当前排序后最小的边(采用克鲁斯卡尔算法),如果我们把白色的边增大,那么这棵最小生成树里面的白色边就会少一些(因为边越大,排序的次序就越靠后),反之亦然。那么我们跑一个二分,把所有白边减一个mid,如果在此时最小生成树的白边数量比题目要求大,就说明目前mid的值大了,将其减少,否则将其增大。当此时最小生成树的白边数量等于题目所给的need时,说明此时的最小生成树即使满足题目要求的最佳情况,且因为此时最小生成树的值是在所有白边都减了一个mid的基础之上,所以答案还需增加一个need*mid;
有一位大佬问了我一个问题:

个人认为你并没有说明可以一定可以取到一个值使得恰好为k个

那么下面附上我的回答(感谢这位大佬!!!)

因为mid的值是没有范围的,所以我们可以通过mid的大小让所有的白边比最小的黑边还小,或者让他们比最大的黑边还大,
那么在确保黑边有n-1条后,我们可以让白边的数量通过mid确定范围为0~n-1,所以一定有一个值使得恰好为k个(只要黑边数
量大于n-1)

代码

#include<bits/stdc++.h>
using namespace std;

struct zz{
   
	int u,v,w,col;
}a[100005];

int pre[50005];
int n,m,k;

int Find(int x){
   
	if(pre[x]!=x){
   
		pre[x]
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值