[每日一题]:建立联系 -- 最小生成树
题目:
考察点:
最小生成树,语文阅读能力的水平
侃侃:
首先,题目中给的 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 见祖宗。
(精辟)
如果说年轻人未来是一场盛宴的话,那么我首先要有赴宴的资格。