次小生成树的裸题
#include <bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
const int N = 1010;
double g[N][N], mincost[N], cost[N], pos[N][2], path[N][N];
double radio, A, B;
int pre[N], n;
bool vis[N], used[N][N];
double cal_dis(double x1, double y1, double x2, double y2){
return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
void prim(){
A = B = 0;
memset(vis, false, sizeof(vis));
memset(used, false, sizeof(used));
memset(path, 0, sizeof(path));
vis[1] = true;
for(int i = 1; i <= n; i ++){
mincost[i] = g[1][i];
pre[i] = 1;
}
for(int i = 1; i < n; i ++){
int u = -1;
for(int j = 1; j <= n; j ++){
if(! vis[j]){
if(u == -1 || mincost[j] < mincost[u])
u = j;
}
}
used[u][pre[u]] = used[pre[u]][u] = true;
B += g[pre[u]][u];
vis[u] = true;
for(int j = 1; j <= n; j ++){
if(vis[j] && j != u){
path[u][j] = path[j][u] = max(path[j][pre[u]], mincost[u]);
}
if(! vis[j]){
if(mincost[j] > g[u][j]){
mincost[j] = g[u][j];
pre[j] = u;
}
}
}
}
}
int main(){
int T;
scanf("%d", &T);
while(T --){
scanf("%d", &n);
memset(g, 0, sizeof(g));
for(int i = 1; i <= n; i ++){
scanf("%lf %lf %lf", &pos[i][0], &pos[i][1], &cost[i]);
}
for(int i = 1; i <= n; i ++){
for(int j = 1; j <= n; j ++){
if(i != j){
g[i][j] = cal_dis(pos[i][0], pos[i][1], pos[j][0], pos[j][1]);
}
}
}
prim();
radio = -inf;
for(int i = 1; i <= n; i ++){
for(int j = 1; j <= n; j ++){
if(i != j){
if(used[i][j]){
radio = max(radio, (cost[i] + cost[j]) / (B - g[i][j]));
}
else{
radio = max(radio, (cost[i] + cost[j]) / (B - path[i][j]));
}
}
}
}
printf("%.2f\n", radio);
}
return 0;
}