[每日一题]:建立联系 -- 最小生成树

题目:

考察点:

最小生成树,语文阅读能力的水平

侃侃:

首先,题目中给的 K 并不是要我们去从所有的关系中找 k 个人,而是告诉我们
现在已经有 K 个人组成一团了,那么还有几个人孤苦伶仃呢?当然是 n - k 个
人了,假设 原先的那 k 个人就是一个整体,那么现在要将这 n - k 个人和 k 
组成一个大的整体(请仔细阅读最后的那句话,人与人之间,且一定存在答案)
我们要将 n - k 个人和原来的 k 联合到一起需要几条边呢?

我们发现要想都联系到一起,还需要 n - k 条边。
题目要求我们最后使得连到一起的代价最小,怎么就最小了呢?
我们发现这 k 个人是不确定的,那什么是确定的呢?我们需要加几条边是确定的,也就是我
们可以按照 权值大小进行从小到大排序,找 N - k 条边即可。

Code:

#include <set>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int maxn = 5e5 + 10;

typedef long long LL;

struct node {
	LL u,v,w;
}friends[maxn];

LL fa[maxn];

LL n,m,k;

// 查找 
LL get(LL x) {
	return x == fa[x] ? x : fa[x] = get(fa[x]);
}
// 合并 
void Union(LL x,LL y) {
	LL xx = get(x);
	LL yy = get(y);
	if(xx == yy) return;
	fa[yy] = xx;
	return ;
}

bool cmp(node a,node b) {
	return a.w < b.w;
}

int main(void) {
	scanf("%lld%lld%lld",&n,&m,&k);
	
	for(int i = 1; i <= m; i ++) {
		scanf("%lld%lld%lld",&friends[i].u,&friends[i].v,&friends[i].w);
	}
	// 初始化 
	for(int i = 0; i <= n; i ++) {
		fa[i] = i;
	} 
	// 按照权值从小到大排序 
	sort(friends + 1,friends + 1 + m,cmp);
	
	LL res = 0;
    LL t = 0;
	for(int i = 1; i <= m; i ++) {
		LL u = friends[i].u;
		LL v = friends[i].v;
		// 寻找 n - k 条边即可 
		if(get(u) != get(v)) {
			Union(u,v);
			res += friends[i].w;     
			t ++;
		} 
        if(t == n - k) break;
        
	}
	printf("%lld\n",res);
	return 0;
} 

后记:

计蒜客这模拟赛的题水平可以啊,哈哈,高估了自己,低估了蒜你狠。
在 k 这里还拐个弯,一定要认真读题,否则,调都不知道何处下手。
对了,记得开 long long.
师傅说 :
三年 OI 一场空,不开 long long 见祖宗。
(精辟)
posted @ 2020-04-25 18:54  IceSwords  阅读(127)  评论(0编辑  收藏  举报