[是题解哦] 洛谷 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棵最小生成树
后来仔细读题
一个棉花糖最少要用掉一朵云
发现是求一棵有n-k条边的最小生成树
代码
1 #include<algorithm> 2 #include<iostream> 3 #include<cstdio> 4 using namespace std; 5 6 const int maxn=1005; 7 const int maxm=10005; 8 struct Edge{ 9 int u; 10 int v; 11 int w; 12 }; 13 Edge edge[maxm]; 14 int n,m,k,cnt=0,ans=0; 15 int f[maxn]; 16 17 inline int find(int k){ 18 return f[k]==k?k:f[k]=find(f[k]); 19 } 20 21 void unionn(int x,int y){ 22 x=find(x); 23 y=find(y); 24 f[x]=y; 25 } 26 27 bool cmp(Edge a,Edge b){ 28 return a.w<b.w?1:0; 29 } 30 31 void kruskal(){ 32 for(int i=1;i<=m;i++){ 33 register int x,y; 34 x=find(edge[i].u); 35 y=find(edge[i].v); 36 if(x!=y){ 37 ans+=edge[i].w;//求最小花费 38 cnt++; 39 unionn(edge[i].u,edge[i].v); 40 } 41 if(cnt==n-k) 42 break; 43 } 44 } 45 46 int main(){ 47 scanf("%d%d%d",&n,&m,&k); 48 if(m<n-k){//边数显然不能少于n-k 49 printf("No Answer"); 50 return 0; 51 } 52 for(int i=1;i<=n;i++) 53 f[i]=i;//认自己为父亲 54 for(int i=1;i<=m;i++) 55 scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w); 56 sort(edge+1,edge+m+1,cmp);//克鲁斯卡尔不可缺少的排序 57 kruskal(); 58 printf("%d",ans); 59 return 0; 60 }
友情链接:安利一只小姐姐的博客