http://acm.hdu.edu.cn/showproblem.php?pid=1875
畅通工程再续
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 38221 Accepted Submission(s): 12808
Problem Description
相信大家都听说一个“百岛湖”的地方吧,百岛湖的居民生活在不同的小岛中,当他们想去其他的小岛时都要通过划小船来实现。现在政府决定大力发展百岛湖,发展首先要解决的问题当然是交通问题,政府决定实现百岛湖的全畅通!经过考察小组RPRush对百岛湖的情况充分了解后,决定在符合条件的小岛间建上桥,所谓符合条件,就是2个小岛之间的距离不能小于10米,也不能大于1000米。当然,为了节省资金,只要求实现任意2个小岛之间有路通即可。其中桥的价格为 100元/米。
Input
输入包括多组数据。输入首先包括一个整数T(T <= 200),代表有T组数据。
每组数据首先是一个整数C(C <= 100),代表小岛的个数,接下来是C组坐标,代表每个小岛的坐标,这些坐标都是 0 <= x, y <= 1000的整数。
Output
每组输入数据输出一行,代表建桥的最小花费,结果保留一位小数。如果无法实现工程以达到全部畅通,输出”oh!”.
Sample Input
2
2
10 10
20 20
3
1 1
2 2
1000 1000
Sample Output
1414.2
oh!
Source
Recommend
lcy | We have carefully selected several similar problems for you: 1102 1272 1301 1162 1325
思路
题目大意:给你几个岛的坐标,只有两个岛的距离在10~1000米范围内的岛才能建立道路。每米道路花费100元。
问:能否建立连接全部岛屿的道路。若能,输出建立道路的最小花费;若不能输出"oh!"。
方法:裸的Kruskal,Debug了数个小时,一直TLE超时,后来发现 while(scanf("%d",&t)){忘记写!=EOF了
AC Code
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int nmax=110;
const int mmax=10010;
int n,m;//点数、边数
struct Edge{
int u,v;//起点、终点、
double val;//边权
}edge[mmax];
bool cmp(Edge a,Edge b){
return a.val<b.val; //按照边权从小到大排序,求最小生成树
}
struct Point{
int x,y;//小岛的坐标
}p[nmax];
double getDist(int i,int j){//得到两个小岛间的距离
return sqrt((p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y));
}
int father[nmax];
int findFather(int u){
if(u==father[u]) return u;
else{
int f=findFather(father[u]);
father[u]=f;
return f;
}
}
void init(int n){
for(int i=0;i<n;++i){
father[i]=i;
}
}
void Kruskal(){//返回最小生成树的边权和
//init(n);
sort(edge,edge+m,cmp);
int cnt=0;//有效合并次数
double ans=0;//最小边权和
for(int i=0;i<m;i++){//遍历m条边
int fu=findFather(edge[i].u);
int fv=findFather(edge[i].v);
if(fu!=fv){
father[fu]=fv;
ans+=edge[i].val;
cnt++;
if(cnt==n-1)//合并了N-1条边,已经找到了最小生成树
break;
}
}
if(cnt==n-1)//找到最小生成树
printf("%.1lf\n",ans*100);
else //图不连通
printf("oh!\n");
}
int main(int argc, char** argv) {
int t;
while(scanf("%d",&t)!=EOF){
while(t--){
memset(father,0,sizeof(father));
scanf("%d",&n);
init(n);
for(int i=0;i<n;i++){
scanf("%d %d",&p[i].x,&p[i].y);
}
int id=0;//有id条边
for(int i=0;i<n-1;++i){
for(int j=i+1;j<n;++j){
double len=getDist(i,j);
//printf("Dist:%.5lf\n",len);
if(len>=10.0 &&len<=1000.0){
edge[id].u=i;edge[id].v=j;edge[id].val=len;
id++;
}
}
}
m=id;
Kruskal();
}
}
return 0;
}