Loading

洛谷P1195 口袋的天空(最小生成树)

题目背景

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

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

题目描述

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

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

输入格式

每组测试数据的

第一行有三个数N,M,K(1≤N≤1000,1≤M≤10000,1≤K≤10)N,M,K(1 \le N \le 1000,1 \le M \le 10000,1 \le K \le 10)N,M,K(1N1000,1M10000,1K10)

接下来MMM行每行三个数X,Y,LX,Y,LX,Y,L,表示XXX云和YYY云可以通过LLL的代价连在一起。(1≤X,Y≤N,0≤L<10000)(1 \le X,Y \le N,0 \le L<10000)(1X,YN,0L<10000)

30%30\%30%的数据N≤100,M≤1000N \le 100,M \le 1000N100,M1000

输出格式

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

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

输入输出样例

输入 #1
3 1 2
1 2 1
输出 #1
1
题目的意思就是将一个图划分成k个连通块,问怎样连边可以使得总边权最小。
先求最小生成树,这样能保证所有节点连起来,这时把n个点划分成k个连通块只需要断掉k-1条边,贪心地选择最大的k-1条边断掉即可。
#include <bits/stdc++.h>
using namespace std;
int fa[1005];
int n,m,k;
struct edge
{
    int x,y,z;
}e[10005];
bool cmp(edge a,edge b)
{
    return a.z<b.z;
}
int get(int x)
{
    if(x==fa[x])return x;
    return fa[x]=get(fa[x]);
}
int main()
{
    int i,ans=0,cnt=0;
    scanf("%d%d%d",&n,&m,&k);
    for(i=1;i<=n;i++)fa[i]=i;
    for(i=1;i<=m;i++)
    {
        int x,y,l;
        scanf("%d%d%d",&x,&y,&l);
        e[i].x=x,e[i].y=y,e[i].z=l;
    }
    sort(e+1,e+m+1,cmp);
    for(i=1;i<=m;i++)
    {
        int x=get(e[i].x),y=get(e[i].y);
        if(x==y)continue;
        fa[x]=y;
        cnt++;
        if(cnt<=n-k)//最小生成树有n-1条边
        {
            ans+=e[i].z;
        }
    }
    cout<<ans<<endl;
    return 0;
}

 



posted @ 2020-04-17 00:20  脂环  阅读(212)  评论(0编辑  收藏  举报