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'。
输入输出样例
说明
厦门一中YMS原创
/* 有一句话说的是 如果n个点被n-1条边连接的话,这一定是棵树。 那么: 连的边数 得到的树的个数 n-1 1 n-2 2 n-3 3 ... ... n-k k 所以我们如果想要连出k棵树,就需要连n-k条边。 题目要求用n朵云连出k个棉花糖。 因为每个棉花糖都是连通的, 那么每个棉花糖就相当于是一棵树。 就是说要用n个节点连出k棵树。 也就是说要用n-k条边连出k棵树。 也就是说要花费连出n-k条边的代价。 既然一定要花费连出n-k条边的代价, 那么当然要选择代价最小的边连起来。 所以给每条可以连的边按代价从小到大排个序, 然后连n-k条边造k个最小生成树就可以了。 如果给的关系数m小于需要连的边数(n-k),是一定连不出k个树来的,因为m个关系只能连m条边。 */ #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #define N 1005 using namespace std; int n,m,k,x,y,l,sum,ans; int fa[N]; struct Edge { int u,v,w; bool operator <(Edge a) const //重置运算符的函数写在里面的话必须加const { return w<a.w; } }edge[N*10]; /*bool operator <(Edge a,Edge b) //重置运算符的函数写在外面的话不能加const { return a.w<b.w; }*/ int read() { char c=getchar();int num=0; for(;!isdigit(c);c=getchar()); for(;isdigit(c);c=getchar()) num=num*10+c-'0'; return num; } int find(int x) { return fa[x]==x?fa[x]:fa[x]=find(fa[x]); } int main() { n=read(),m=read(),k=read(); for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<=m;i++) { edge[i].u=read(),edge[i].v=read(),edge[i].w=read(); } sort(edge+1,edge+m+1); //按代价升序排列 for(int i=1;i<=m;i++) { int fx=find(edge[i].u),fy=find(edge[i].v); if(fx!=fy) //如果这两个点不在同一棵树中 { fa[fx]=fy; sum++; //连一条边,让它们合并成为一棵树 ans+=edge[i].w; //加上合并的代价 } if(sum==n-k) //已经连好了k棵树 { printf("%d",ans); return 0; } } puts("No Answer"); //不可能连好 return 0; }