洛谷 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'。
输入输出样例
输入样例#1: 复制
3 1 2 1 2 1
输出样例#1: 复制
1
算法:生成树 难度:普及+/提高
(虽然网上已经又不少题解了,but还是想来发一个 qwq)
#include<algorithm> #include<iostream> #include<cstdio> #include<cmath> using namespace std; int n, m, k, ta; int tail, kx, sum; int f[100001], team[1000001]; int exist[10001]; struct re { int next, w, t, s, head; } e[10001*4]; void build(int x, int y, int z) { e[++ta].w = z; e[ta].t = y; e[ta].s = x; e[ta].next = e[x].head; e[x].head = ta; } bool cmp(re a, re b) { return a.w < b.w; } int find(int x) { return f[x]==x ? x : f[x]=find(f[x]); } void add(int a,int b) { int ux,uy; ux = find(a); uy = find(b); f[ux] = uy; } int main() { cin >> n >> m >> k; for(int i = 1; i <= m; ++i) { int a, b, c; cin >> a >> b >> c; exist[a] = exist[b] = 1; build(a, b, c); build(b, a, c); } for(int i = 1; i <= n; ++i) { f[i] = i; if(exist[i] == 0) ++kx; } k -= kx; sort(e+1, e+ta+1, cmp); for(int i = 1; i <= ta; ++i) { if(find(e[i].s) != find(e[i].t)) { add(e[i].s, e[i].t); team[++tail] = i; sum += e[i].w; } } for(int i = tail; i > (tail-k+1); --i) { sum -= e[team[i]].w; } if(n<(kx+k) || (kx+1)>k+kx) cout << "No Answer"; else cout << sum; return 0; }