Forever Young

洛谷 P1195 口袋的天空

洛谷 P1195 口袋的天空

题目链接

https://www.luogu.org/problemnew/show/P1195


题目背景

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

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


题目描述

给你云朵的个数N,再给你M个关系,表示哪些云朵可以连在一起。

现在小杉要把所有云朵连成KK个棉花糖,一个棉花糖最少要用掉一朵云,小杉想知道他怎么连,花费的代价最小。


输入输出格式

输入格式:

每组测试数据的

第一行有三个数N,M,K(1N1000,1M10000,1K10)

接下来M个数每行三个数X,Y,L表示X云和Y云可以通过L的代价连在一起。(1X,YN,0L<10000)

30%的数据N <= 100,M <= 1000,N100,M1000

输出格式:

对每组数据输出一行,仅有一个整数,表示最小的代价。

如果怎么连都连不出K个棉花糖,请输出'No Answer'。


思路

有一个定理:N个点用N-1条边连接成一个连通块,形成的图形只可能是树,没有别的可能。

那么有如下的关系: 


所以我们如果想要连出k棵树,就需要连n-k条边。

题目要求用n朵云连出k个棉花糖。因为每个棉花糖都是连通的,那么每个棉花糖就相当于是一棵树。

就是说要用n个节点连出k棵树。即要用n-k条边连出k棵树。

也就是说要花费连出n-k条边的代价。

既然一定要花费连出n-k条边的代价,那么当然要选择代价最小的边连起来。

所以给每条可以连的边按代价从小到大排个序,然后连n-k条边造k个最小生成树就可以了。 

(思路是偷的,代码自己打的,逃!)


代码

#include<iostream>
#include<string>
#include<stack>
#include<queue>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;

int n,m,k;
int sum=0,ans=0;
int pre[1001];

struct bian {
    int u,v,w;
} b[10001];

bool comp(bian a,bian b){
    return a.w<b.w;
}
int find(int x) {
    if(pre[x]==x)return x;
    return pre[x]=find(pre[x]);
}

int main() {
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1; i<=n; i++) pre[i]=i;
    for(int i=1; i<=m; i++) {
        scanf("%d%d%d",&b[i].u,&b[i].v,&b[i].w);
    }
    stable_sort(b+1,b+m+1,comp);
    for(int i=1; i<=m; i++) {
        int fx=find(b[i].u),fy=find(b[i].v);
        if(fx!=fy) {
            pre[fx]=fy;
            sum++;
            ans+=b[i].w;
        }
        if(sum==n-k) {
            cout<<ans;
            return 0;
        }
    }
    printf("No Answer");
    return 0;
}

 

posted @ 2019-04-12 14:31  Loceaner  阅读(190)  评论(0编辑  收藏  举报