【洛谷】【最小生成树】P1195 口袋的天空

【题目背景:】

小杉坐在教室里,透过口袋一样的窗户看口袋一样的天空。

有很多云飘在那里,看起来很漂亮,小杉想摘下那样美的几朵云,做成棉花糖。

【题目描述:】

给你云朵的个数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
", tot);
}
原文地址:https://www.cnblogs.com/devilk-sjj/p/9088346.html