链接:http://acm.hdu.edu.cn/showproblem.php?pid=4081
来源:2011 Asia Beijing Regional Contest
#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
typedef long long ll;
const int Max_n=1e3+10;
double cost[Max_n][Max_n],dis[Max_n];
double path[Max_n][Max_n],ans;
bool used[Max_n][Max_n],vis[Max_n];
int pre[Max_n],n;
struct Node{
int x,y,peo;
}node[Max_n];
double cal(int i,int j){
return sqrt((node[i].x-node[j].x)*(node[i].x-node[j].x)+(node[i].y-node[j].y)*(node[i].y-node[j].y));
}
double Prim(){
double ans=0;
vis[1]=true;
for(int i=1;i<=n;i++){
dis[i]=cost[1][i];
pre[i]=1;
}
for(int i=2;i<=n;i++){
double minc=inf; int p=-1;
for(int j=1;j<=n;j++){
if(!vis[j]&&dis[j]<minc){
minc=dis[j];
p=j;
}
}
if(minc==inf) return -1;
ans+=minc;
vis[p]=true;
used[p][pre[p]]=used[pre[p]][p]=true;
for(int j=1;j<=n;j++){
if(vis[j]&&j!=p){
path[j][p]=path[p][j]=max(path[j][pre[p]],dis[p]);
//要么是新添加的边,要么是原来最长的
}
if(!vis[j]&&dis[j]>cost[j][p]){
dis[j]=cost[p][j];
pre[j]=p;
}
}
}
return ans;
}
int main(){
int T; scanf("%d",&T);
while(T--){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d%d%d",&node[i].x,&node[i].y,&node[i].peo);
for(int i=1;i<=n;i++){
vis[i]=false; dis[i]=inf;
for(int j=1;j<=n;j++){
used[i][j]=false;
path[i][j]=0;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++)
cost[i][j]=cal(i,j);
}
//for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) printf("%.2f%c",cost[i][j],j==n?'\n':' ');
double res=Prim();
double ans=0;//先求出最小生成树,遍历边,找次小生成树或者直接删除边
//cout<<" "<<ans<<endl;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==j) continue;
if(used[i][j]) ans=max(ans,(node[i].peo+node[j].peo)/(res-cost[i][j]));
else ans=max(ans,(node[i].peo+node[j].peo)/(res-path[i][j]));
}
}
printf("%.2f\n",ans);
}
return 0;
}