给你n个城市 每个城市有一定数量的人 连接2个城市需要的花费是他们之间的距离 现在要建一颗最小生成树 可以免费建其中一条边 设A为免费的那条边连接的2个城市的人口之和 B为修建的最小生成树的花费 求最大的A/B
先求最小生成树 设总花费为totol 然后可以枚举免费的那条边 枚举边等于A确定 在这条在最小生成树里的情况下 求最小的B
如果这条边是最小生成树里的边 那么很容易求得B 拿totol减去这条边就行了
如果不是 那么把这条边加到最小生成树 会出现一个环 找到这个环最大的那条边剪掉 就是次小生成树的做法 然后类似求A/B
n^2预处理任意2点之间唯一路径上的最大边权
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
using namespace std;
const int maxn = 1010;
struct poit
{
double x, y, p;
}p[maxn];
struct edge
{
double dis;
int u, v, next;
bool select;
}e[maxn*maxn], G[maxn*2];
struct node
{
double dis;
int u, v;
node(){}
node(int u, int v, double d): u(u), v(v), dis(d) {}
};
int n;
double dp[maxn][maxn], totol;
int f[maxn];
int first[maxn], cnt;
void AddEdge(int u, int v, double w)
{
G[cnt].u = u;
G[cnt].v = v;
G[cnt].dis = w;
G[cnt].next = first[u];
first[u] = cnt++;
G[cnt].u = v;
G[cnt].v = u;
G[cnt].dis = w;
G[cnt].next = first[v];
first[v] = cnt++;
}
void init()
{
for(int i = 1; i <= n; i++)
f[i] = i;
totol = 0;
memset(dp, 0, sizeof(dp));
memset(first, -1, sizeof(first));
cnt = 0;
}
int find(int x)
{
if(x != f[x])
return f[x] = find(f[x]);
return f[x];
}
double Dist(int i, int j)
{
return sqrt((double)(p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y));
}
bool cmp(edge a, edge b)
{
return a.dis < b.dis;
}
void MST(int l)
{
for(int i = 0; i < l; i++)
{
int x = find(e[i].u);
int y = find(e[i].v);
if(x != y)
{
totol += e[i].dis;
f[x] = y;
e[i].select = true;
AddEdge(e[i].u, e[i].v, e[i].dis);
}
}
}
void BFS(int x)
{
queue <node> Q;
Q.push(node(-1, x, 0));
while(!Q.empty())
{
node u = Q.front(); Q.pop();
for(int i = first[u.v]; i != -1; i = G[i].next)
{
if(G[i].v == u.u)
continue;
double temp = max(u.dis, G[i].dis);
dp[x][G[i].v] = max(dp[x][G[i].v], temp);
Q.push(node(u.v, G[i].v, temp));
}
}
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
scanf("%d", &n);
init();
for(int i = 1; i <= n; i++)
scanf("%lf %lf %lf", &p[i].x, &p[i].y, &p[i].p);
int l = 0;
for(int i = 1; i <= n; i++)
{
for(int j = i+1; j <= n; j++)
{
if(i == j)
continue;
e[l].u = i;
e[l].v = j;
e[l].select = false;
e[l].dis = Dist(i, j);
l++;
}
}
sort(e, e+l, cmp);
MST(l);
for(int i = 1; i <= n; i++)
BFS(i);
double ans = 0.0;
for(int i = 0; i < l; i++)
{
int u = e[i].u, v = e[i].v;
if(e[i].select)
{
double tmp = (p[u].p + p[v].p) / (totol-e[i].dis);
ans = max(ans, tmp);
}
else
{
double tmp = (p[u].p + p[v].p) / (totol-dp[u][v]);
ans = max(ans, tmp);
}
}
printf("%.2lf\n", ans);
}
return 0;
}