N - 畅通工程再续
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!
题意:给定小岛的坐标,建桥实现任意两个小岛之间有路通即可。
题解:简单的最小生成树,在边权值的判断中加入如果小于10或者大于1000都不能通过即可,最后看求出来的最小权值和是否小于inf。
AC代码:
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<cmath>
using namespace std;
int n,t,m;
double sum;
const int maxn = 107;
const int inf = 0x3f3f3f3f;
double a[maxn][maxn];
double b[maxn];
double x[maxn],y[maxn];
double length[maxn];
int vis[maxn];
int path[maxn];
void prim()
{
for(int i=1;i<=n;i++)
{
vis[i]=0;
length[i]=a[1][i];
}
for(int i=1;i<=n;i++)
{
double u=inf;
int v;
for(int j=1;j<=n;j++)
{
if(vis[j]==0&&length[j]<u)
{
u=length[j];
v=j;
}
}
vis[v]=1;
sum+=length[v];
for(int j=1;j<=n;j++)
{
if(vis[j]==0&&length[j]>a[v][j])
{
length[j]=a[v][j];
}
}
}
}
double leng(double x1,double y1,double x2,double y2)
{
double k=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
return k;
}
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>n;
sum=0;
for(int i=1;i<=n;i++)cin>>x[i]>>y[i];
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j++)
{
double k=leng(x[i],y[i],x[j],y[j]);
if(j==i)a[i][j]=0;
else if(k<10||k>1000)a[i][j]=a[j][i]=1e9;
else a[i][j]=a[j][i]=k;
}
prim();
if(sum<1e9)printf("%.1f\n",sum*100);
else cout<<"oh!"<<endl;
}
return 0;
}