【题目背景:】
小杉坐在教室里,透过口袋一样的窗户看口袋一样的天空。
有很多云飘在那里,看起来很漂亮,小杉想摘下那样美的几朵云,做成棉花糖。
【题目描述:】
给你云朵的个数N,再给你M个关系,表示哪些云朵可以连在一起。
现在小杉要把所有云朵连成K个棉花糖,一个棉花糖最少要用掉一朵云,小杉想知道他怎么连,花费的代价最小。
【输入格式:】
每组测试数据的
第一行有三个数N,M,K(1<=N<=1000,1<=M<=10000,1<=K<=10)
接下来M个数每行三个数X,Y,L,表示X云和Y云可以通过L的代价连在一起。(1<=X,Y<=N,0<=L<10000)
30%的数据N<=100,M<=1000
【输出格式:】
对每组数据输出一行,仅有一个整数,表示最小的代价。
如果怎么连都连不出K个棉花糖,请输出'No Answer'。
[算法分析:]
一看就是最小生成树,关键在于怎样“连成K个棉花糖”花费的代价最小.
由于一朵云就可以是一个棉花糖,所以那些连边代价大的云朵就不要连,
也就是说有\((k-1)\)朵云不要去管他们,剩下的\((n-k+1)\)朵云连成一个棉花糖,总共使用了\(n\)朵云连成了\(k\)个棉花糖.
使用Kruskal做MST,连\((n-k)\)条边就好.
[Code:]
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN = 1000 + 1;
const int MAXM = 10000 + 1;
int n, m, k;
int fa[MAXN];
struct Edge {
int x, y, l;
}h[MAXM];
inline bool cmp(Edge a, Edge b) {
return a.l < b.l;
}
int find(int x) {
if(fa[x] != x) fa[x] = find(fa[x]);
return fa[x];
}
int main() {
scanf("%d%d%d", &n, &m, &k);
for(int i=1; i<=n; ++i) fa[i] = i;
for(int i=1; i<=m; ++i)
scanf("%d%d%d", &h[i].x, &h[i].y, &h[i].l);
sort(h + 1, h + m + 1, cmp);
int tot = 0, num = 0;
for(int i=1; i<=m; ++i) {
int fx = find(h[i].x), fy = find(h[i].y);
if(fx != fy) {
fa[fx] = fy;
tot += h[i].l;
++num;
}
if(num == n-k) break;
}
if(num < n-k) puts("No Answer");
else printf("%d\n", tot);
}