Vijos:P1234口袋的天空

背景

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

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

描述

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

输入:

3 1 2
1 2 1

输出

1

思路:N朵云最多做N个棉花糖,多连一条边就少做一个棉花糖。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=10005;
struct Edge{
    int u,v,w;
}es[MAXN];
int n,m,k;
int par[MAXN],rnk[MAXN];
bool comp(const Edge &e1,const Edge &e2)
{
    return e1.w < e2.w;
}
void prep()
{
    for(int i=0;i<MAXN;i++)
    {
        par[i]=i;
        rnk[i]=0;
    }
}
int fnd(int x)
{
    if(par[x]==x)
        return x;
    return par[x]=fnd(par[x]);
}
void unite(int u,int v)
{
    int a=fnd(u);
    int b=fnd(v);
    if(a==b)    return ;
    if(rnk[a]<rnk[b])
    {
        par[a]=b;
    }
    else
    {
        par[b]=a;
        if(rnk[a]==rnk[b])    rnk[a]++;
    }
}
bool same(int u,int v)
{
    return fnd(u)==fnd(v);
}
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for(int i=0;i<m;i++)
    {
        scanf("%d%d%d",&es[i].u,&es[i].v,&es[i].w);
    }
    if(k==n)
    {
        printf("0
");
        return 0;
    }
    if(k>n)
    {
        printf("No Answer
");
        return 0;
    }
    sort(es,es+m,comp);
    prep();
    int cnt=0;
    int res=0;
    for(int i=0;i<m;i++)
    {
        if(!same(es[i].u,es[i].v))
        {
            unite(es[i].u,es[i].v);
            res+=es[i].w;
            cnt++;
            if(n-cnt==k)
            {
                break;
            }
        }
    }
    if(n-cnt==k)
        printf("%d
",res);
    else
        printf("No Answer
");
    
    return 0;
} 
原文地址:https://www.cnblogs.com/program-ccc/p/5360917.html