//给出每点的坐标和其到人口量,找一个生成树,其中有一条边造价为0
//问A/B的最大值,A这条边连接的两个点的人口之和
//B除了这条边以外的其他边的长度之和
//先找到最小生成树,然后枚举所有边,如果这条边是最小生成树上的边,
//直接计算A/(sum-edge) ,如果不是,那么这条边加在最小生成树上会出现一个
//环,去除这个环中的最长的边依然是一棵树,
//用dp[u][v] 表示在最小生成树中从u到v的唯一路径所经过的最长边的大小
//dp[u][v[i]] = dp[v[i]][u]= max(map[F[u]][u] , dp[F[u]][v[i]]) ;
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
using namespace std ;
const int maxn = 1010 ;
const int inf = 0x3f3f3f3f ;
double dp[maxn][maxn] ;
double map[maxn][maxn] ;
double x[maxn] , y[maxn] , p[maxn] ;
int F[maxn] ;int vis[maxn] ;
int v[maxn] ;double dis[maxn] ;
int n ;
double prim()
{
int len = 0 ;
memset(vis ,0 ,sizeof(vis)) ;
memset(dp , 0 , sizeof(dp)) ;
for(int i = 2;i <=n; i++)
dis[i] = inf ;
dis[1] = 0 ;F[1] = 1 ;
v[++len] = 1 ;
double ans = 0 ;
while(1)
{
double mi = inf ;int u ;
for(int i = 1;i <= n;i++)
if(!vis[i]&&dis[i] < mi)
mi = dis[u = i] ;
if(mi == inf)break;
vis[u] = 1;
ans += mi ;
for(int i = 1;i <= len ;i++)
dp[u][v[i]] = dp[v[i]][u]= max(map[F[u]][u] , dp[F[u]][v[i]]) ;
v[++len] = u ;
for(int i = 1;i <= n;i++)
if(!vis[i] && map[u][i] < dis[i])
{
dis[i] = map[u][i] ;
F[i] = u ;
}
}
return ans ;
}
int main()
{
//freopen("in.txt" ,"r" , stdin) ;
int t ;
scanf("%d" , &t) ;
while(t--)
{
scanf("%d" , &n) ;
for(int i = 1;i <= n;i++)
{
scanf("%lf%lf%lf" , &x[i] , &y[i] , &p[i]) ;
for(int j = 1;j <= i;j++)
map[i][j] = map[j][i] = sqrt((x[i]-x[j])*(x[i]-x[j]) + (y[i] - y[j])*(y[i]-y[j])) ;
}
double sum = prim() ;
double ans = 0 ;
for(int i = 1;i <= n;i++)
for(int j = 1; j < i ;j++)
ans = max(ans , (p[i] + p[j])/(sum - dp[i][j])) ;
printf("%.2lf\n" , ans) ;
}
return 0 ;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
hdu4081Qin Shi Huang's National Road System 次小生成树
原文地址:http://blog.csdn.net/cq_pf/article/details/47272113