UVa 11733 Airports(变形的最小生成树)

Airports

The government of a certain developing nation wants to improve transportation in one of its most inaccessible areas, in an attempt to attract investment. The region consists of several important locations that must have access to an airport.

 

Of course, one option is to build an airport in each of these places, but it may turn out to be cheaper to build fewer airports and have roads link them to all of the other locations. Since these are long distance roads connecting major locations in the country (e.g. cities, large villages, industrial areas), all roads are two-way. Also, there may be more than one direct road possible between two areas. This is because there may be several ways to link two areas (e.g. one road tunnels through a mountain while the other goes around it etc.) with possibly differing costs.

 

A location is considered to have access to an airport either if it contains an airport or if it is possible to travel by road to another location from there that has an airport.

 

You are given the cost of building an airport and a list of possible roads between pairs of locations and their corresponding costs. The government now needs your help to decide on the cheapest way of ensuring that every location has access to an airport. The aim is to make airport access as easy as possible, so if there are several ways of getting the minimal cost, choose the one that has the most airports.

 

Note: The input file is large; make sure your I/O code is fast.

 

 

Input

 

The first line of input contains the integer T(T<25), the number of test cases. The rest of the input consists of T cases.

 

Each case starts with three integers NM and A (0<N<=10,000, 0<=M<=100,000, 0<A<=10,000) separated by white space. N is the number of locations, M is the number of possible roads that can be built, and A is the cost of building an airport.

 

The following M lines each contain three integers XY and C (1<=XY<=N, 0<C<=10,000), separated by white space. X and Y are two locations, and C is the cost of building a road between X and Y.

 

Output

 

Your program should output exactly T lines, one for each case. Each line should be of the form "Case #X: Y Z", where X is the case number Y is the minimum cost of making roads and airports so that all locations have access to at least one airport, and Z is the number of airports to be built. As mentioned earlier, if there are several answers with minimal cost, choose the one that maximizes the number of airports.

 

 

Sample Input

Sample Output

2

4 4 100

1 2 10

4 3 12

4 1 41

2 3 23

5 3 1000

1 2 20

4 5 40

3 2 30

Case #1: 145 1

Case #2: 2090 2

 




题意 :有N个小镇(N<=10000),现在可以修建M条无向道路(M<=100000)。并且修建每条路

有各自的费用,现在要在小镇设立飞机场,要求每个小镇都可以到达至少一个飞机场,并且

建设飞机场的费用是A,求满足条件的最少费用,并且在这个最少费用下,飞机场最多可以

建设几个。

思路 :首先求出图中连通块的个数 num ,在用Kruskal 一边 ,这样就能使每个连通块保持连通性,

且使得费用最小。然后在遍历每个连通块的边,找出边费用大于或等于飞机场费用的个数 coun ,即建飞

场的个数就是 cnt = num + coun ;最小费用 sum = cnt * A + tp 。 (tp为每个连通块中边费用小于飞机

费用的边费用的总和)。


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
const int maxn=100010;

struct node
{
    int u,v,cost;
}a[maxn];

int n,m,A,cnt,id[maxn],visited[maxn];
vector <int > v;

bool cmp(node p,node q)
{
    return p.cost<q.cost;
}

int Find(int x)
{
    if(x!=id[x]) id[x]=Find(id[x]);
    return id[x];
}

void input()
{
    scanf("%d %d %d",&n,&m,&A);
    for(int i=0;i<m;i++)  scanf("%d %d %d",&a[i].u,&a[i].v,&a[i].cost);
    sort(a,a+m,cmp);
}

void initial()
{
    memset(visited,0,sizeof(visited));
    for(int i=0;i<=n;i++)  id[i]=i;
    v.clear();
    cnt=0;
}

void kru()
{
    for(int i=0;i<m;i++)
    {
        int p=Find(a[i].u),q=Find(a[i].v);
        if(p!=q)
        {
            id[p]=q;
            v.push_back(a[i].cost);
        }
    }
    for(int i=1;i<=n;i++)  if(!visited[Find(i)])  visited[Find(i)]=1,cnt++;
}

void solve(int co)
{
    kru();
    int len=v.size(),t=len,sum=0;
    for(int i=0;i<len;i++)
    {
        if(v[i]>=A)
        {
            t=i;
            break;
        }
        sum+=v[i];
    }
    int num=cnt+len-t;
    sum+=num*A;
    printf("Case #%d: %d %d\n",co,sum,num);
}

int main()
{
    int T;
    scanf("%d",&T);
    for(int co=1;co<=T;co++)
    {
        input();
        initial();
        solve(co);
    }
    return 0;
}



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值