[是题解哦] 洛谷 P1195 口袋的天空

题目链接

点这里ww

 

题目背景

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

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

 

题目描述

给你云朵的个数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 }

 

友情链接:安利一只小姐姐的博客

 

posted @ 2018-09-25 19:57  多多良小伞  阅读(161)  评论(0编辑  收藏  举报