【图论训练】优惠

优惠

favor.pas/c/cpp

 

【题目描述】

现有一国家要修建水利供应系统,该国首脑希望连接起所有城市。供应商提出了一些连接城市ai, bi的方案,每个方案有一个资金消耗wi,首脑希望花费最少代价来连接所有城市。经过多次协商,供应商愿意免费修建不超过k个方案。求最少的连接所有城市的花费。

 

【输入】

输入第一行有三个数n, m, k,分别表示该国城市数和连接城市的方案数以及供应商愿意提供的免费修建方案数。

接下来的m行,每行有三个整数ai, bi, wi,分别表示第i个方案是连接ai和bi城市,花费为wi。

 

【输出】

输出仅一行,包含一个整数,表示连接所有城市所需花费,数据保证方案足够连通所有城市的。

 

【输入样例】

4 5 1

1 2 5

3 4 6

1 3 9

2 4 3

4 1 7

 

【输出样例】

8

 

【数据规模】

20%的数据满足:k=0,1<=n<=m<=1000

50%的数据满足:k<=1, 1<=n<=m<=1000

100%的数据满足:输入中所有数均为非负整数,2<=n<=100000, 1<=m<=100000, 1<=ai, bi<=n, wi<=10000。

保证至少存在一种可行方案,使得所有城市可以连接在一起

 

显然是最小生成树l(。・_・。)ノ裸的kruskal

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,k;
struct node{
    int u,v;
    int value;
}e[200001];
int father[100001];
bool cmp(node e1,node e2)
{
    return e1.value<e2.value;
}
void read()
{
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=m;i++)
    {
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        e[i].u=u;
        e[i].v=v;
        e[i].value=w;
    }
    sort(e+1,e+m+1,cmp);
}
int find(int x)
{
    if(father[x]==x) return x;
    else return father[x]=find(father[x]);
}
void merge(int x,int y)
{
    if(find(x)!=find(y)) father[father[x]]=father[y];
}
void kruskal()
{
    for(int i=1;i<=n;i++) father[i]=i;
    int ans=0;
    int sum=0;
    for(int i=1;i<=m;i++)
    {
        if(find(e[i].u)!=find(e[i].v))
        {
            if(sum<n-k-1) ans+=e[i].value;
            sum++;
            merge(e[i].u,e[i].v);
        }
        if(sum==n-1) break;
    }
    printf("%d",ans);
    return;
}
int main()
{
    freopen("favor.in","r",stdin);
    freopen("favor.out","w",stdout);
    read();
    kruskal();
    return 0;
}

 

posted @ 2015-10-26 15:24  Oranges  阅读(127)  评论(0编辑  收藏  举报