洛谷 P1195

题目背景

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

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

题目描述

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

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

输入输出格式

输入格式:

每组测试数据的

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

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

30%的数据1000N100,M1000

输出格式:

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

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

解析

题目特别坑,

连的边数 得到的树的个数

n-1 1

n-2 2

n-3 3

... ...

n-k k

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

也就是说最后是n-k条边而不是k-1条边;

明白这一点就是一个简单的kruscal

代码

#include<bits/stdc++.h>
using namespace std;

int n,m,k;
int f[5005];

void clean()
{
    for(int i=1;i<=n;i++)
    {
        f[i]=i;
    }
}//初始化并查集 

int mf(int v)
{
    if(f[v]==v) return v;
    else
    {
        f[v]=mf(f[v]);
        return f[v];
    }
}//找爹 

void mer(int a,int b)
{
    int af=mf(a);
    int bf=mf(b);
    if(af!=bf)
    {
        f[bf]=af;
    }
}//合并 

struct make_edge
{
    int a;
    int b;
    int w;
};//每条边 

make_edge edge[200005];

bool cmp(make_edge a,make_edge b)
{
    return a.w<b.w;
}

int main()
{
    cin>>n>>m>>k;
    clean();
    for(int i=1;i<=m;i++)
    {
        int a,b,w;
        cin>>a>>b>>w;
        edge[i].a=a;
        edge[i].b=b;
        edge[i].w=w;
    }
    sort(edge+1,edge+m+1,cmp);//排序 
    int count=0;//边数 
    int sum=0;
    for(int i=1;i<=m;i++)
    {
        if(mf(edge[i].a)==mf(edge[i].b)) continue;
        else
        {
            mer(edge[i].a,edge[i].b);
            sum+=edge[i].w;
            count++;
        }
        if(count==n-k)
        {
            break;
        }
    }
    if(count<n-k) cout<<"No Answer"<<endl;
    else cout<<sum<<endl;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/KyleDeng/p/9814867.html
今日推荐