UVA, 11733 (kruscal,最小生成树)

Airports

From:UVA,
11733

Submit

Time Limit: 1000 MS


   

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个城镇,m条马路,需要建造飞机场,建造马路和飞机场的费用告诉你,让你输出在村庄都可达飞机场的情况下最小花费和在最小花费下所能建造的最多的飞机场的数目。

解题思路:

kruscal算法,对边排序,当边的费用大于飞机场的费用时,舍弃边,建造飞机场数目cnt++,最后飞机场的cnt=cnt+集合的个数。算出费用和。

代码:

#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;

struct edge{int u,v,cost;};

const int maxm=100010,maxn=10010;

bool cmp(const edge& e1,const edge& e2){
    return e1.cost<e2.cost;
}

edge ed[maxm];
int v,e,air,parent[maxn],cnt,res,rank[maxn];
vector <int> myve;

void input(){
    scanf("%d%d%d",&v,&e,&air);
    for(int i=0;i<e;i++){
        scanf("%d %d %d",&ed[i].u,&ed[i].v,&ed[i].cost);
    }
}

void inti_union_find(int v){
    for(int i=0;i<=v;i++){
        parent[i]=i;
        rank[i]=1;
    }
}

void Union(int a,int b){
    if(rank[a]<rank[b]){
        parent[a]=b;
    }
    else{
        if(rank[a]==rank[b]) rank[a]++;
        parent[b]=a;
    }
}

int find(int x){return parent[x]==x?x:parent[x]=find(parent[x]);}

void kruskal(){
    sort(ed,ed+e,cmp);
    inti_union_find(v);
    res=0;
    cnt=0;
    for(int i=0;i<e;i++){
        edge tempe=ed[i];
        int p=find(tempe.u);
        int q=find(tempe.v);
        if(q!=p){
            Union(p,q);
            res+=tempe.cost;
            if(tempe.cost>=air){
                res-=tempe.cost;
                cnt++;
            }
        }
    }
}

void solve(){
    for(int i=1;i<=v;i++){
        if(find(i)==i)
            cnt++;
    }
    res+=air*cnt;
}

int main(){
    int t,casen=0;
    scanf("%d",&t);
    while(t--){
        input();
        kruskal();
        solve();
        printf("Case #%d: %d %d\n",++casen,res,cnt);
    }
    return 0;
}

时间: 2024-10-06 09:14:02

UVA, 11733 (kruscal,最小生成树)的相关文章

UVa 11354 Bond 最小生成树+LCA倍增

题目来源:UVa 11354 Bond 题意:n个点m条边的图 q次询问 找到一条从s到t的一条边 使所有边的最大危险系数最小 思路:使最大的危险系数尽量小 答案是最小生成树上的边 然后用LCA倍增法记录s和t到他们最近公共祖先的最大值 #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 50010; const int INF =

uva 11354 bond 最小生成树

n个城市通过m条无向边连接,回答q个询问,每个询问形式为s,t,要找到一条s到t的路使得这条路上的最大危险系数最小. 还是最小瓶颈路,可是要快速回答每次询问,先求出最小生成树,转化为有根树,即找到s到t的路径上的最大边,在这一过程中倍增查找. 预处理的复杂度为nlogn,每次查询为logn. #include <cstdio> #include <cstring> #include <vector> #include <algorithm> using na

训练指南 UVA - 11354(最小生成树 + 倍增LCA)

layout: post title: 训练指南 UVA - 11354(最小生成树 + 倍增LCA) author: "luowentaoaa" catalog: true mathjax: true tags: - 最小生成树 - LCA - 图论 - 训练指南 Bond UVA - 11354 题意 给你一张无向图,然后有若干组询问,让你输出a->b的最小瓶颈路 题解 先求出最小生成树,然后对这个最小生成树做LCA. #include<bits/stdc++.h>

BZOJ 1083: [SCOI2005]繁忙的都市【Kruscal最小生成树裸题】

1083: [SCOI2005]繁忙的都市 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2925  Solved: 1927[Submit][Status][Discuss] Description 城市C是一个非常繁忙的大都市,城市中的道路十分的拥挤,于是市长决定对其中的道路进行改造.城市C的道 路是这样分布的:城市中有n个交叉路口,有些交叉路口之间有道路相连,两个交叉路口之间最多有一条道路相连 接.这些道路是双向的,且把所有的交叉路口直接或

UVA 11354 Bond(最小生成树+lca+倍增求祖先节点)

题意:n个点m条边,每条边有一个权值,有q个询问,每次询问两点间的一条路径,使得这条路径上权值最大的边最小. 思路:很容易想到最小瓶颈路,但是查询太多,会超时,可以预处理出最小生成树,则问题转化为一棵树上的两点间路径中权值最大的那条边,设这两点为u,v,可以得到dist(u,v)=max(dist(u,lca(u,v)),dist(v,lca(v,lca))),其中lca(u,v)表示u和v的最近公共祖先,用倍增的思想预处理出每个结点的2^i的祖先fa[u][i],然后在离线求出lca后顺便计算

uva 1151(最小生成树,枚举子集)

题意:平面上有n个点(1<=N<=1000),你的任务是让所有n个点连通,为此,你可以新建一些边,费用等于两个端点的欧几里得距离的平方.另外还有q(0<=q<=8)个套餐,可以购买,如果你购买了第i个套餐,该套餐中的所有结点将变得相互连通,第i个套餐的花费为ci. kruskal: 先求一次原图的最小生成树,得到n-1条边,然后每次枚举完套餐后只考虑套餐中的边和这n-1条边,则枚举套餐之后再求最小生成树. key: kruskal算法中,那些两端已经属于同一个连通分量的边不会再加到

UVA 11354 - Bond (最小生成树 + 树链剖分)

题目链接~~> 做题感悟:这题开始看到时感觉不是树不好处理,一想可以用 Kruskal 处理成树 ,然后就好解决了. 解题思路: 先用 Kruskal 处理出最小生成树,然后用树链剖分 + 线段树处理就可以了. 代码: #include<iostream> #include<sstream> #include<map> #include<cmath> #include<fstream> #include<queue> #incl

UVA 11354 LCA+最小生成树

点击打开链接 题意:给一个无向图,然后有Q次询问U V,问的是U到V的所有路径中的最小值最大 思路:U到V的路径最小值最大,则这条边肯定是最小生成树上的边,那么我们可以先将所有的最小生成树上的边全都找出来,然后现在是一个树,然后跑一边LCA,对于现在询问的U到V,只要找到它们的最近公共祖先,然后两个点向上找到它,比较路径中的最大值即可  PS:这么暴力找跑得有点慢 #include <vector> #include <stdio.h> #include <string.h&

UVa 1395 (最小生成树)

题目链接:http://vjudge.net/problem/41567/origin 本来想着m^2的复杂度撑不住,对于这种擦着边的复杂度就好慌. 首先对所有的边排个序,然后枚举每个可以构成生成树的区间(L,R),取区间里面构成树的边的权值的最小和最大的差值,求最小值即可. 如果已经构成生成树可以break掉优化下. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include &l