这个题确实不简单,难就难在对题意的正确的理解上,
题意;
秦始皇想要修路使得n个城市连通,同时使得这些路尽量短。这时徐福说他可以在2个城市之间不花费人力物力建一条路,但他只能建1条这样的路。秦始皇想要使除了徐福造的那条路以外的路的总长度尽量短,而徐福想要造福更多的百姓,他想要使自己用法术建的那条路的两端的城市的总人口数最多。最终二人达成协议。假设A=用法术建的那条路的两端的城市的总人口数,B=除了徐福造的那条路以外的路的总长度,建造的路要使得A/B最大。输出A/B。
咱们先来分析一下这个题,一开始以为是直接在最小生成树上枚举边就行,再仔细一想,不对啊,最小生成树不唯一,这样枚举肯定不对啊,再去读题才明白,徐福建的这条路不一定是在最小生成树上,只要满足A / B 最大就可以,这样就可以分为两种情况
第一种情况是 如果这条边在最小生成树上的话,那直接就是 这条边相连的城市的 人口之和 / MST - 边权
第二种情况是 如果这条边不在最小生成树上的话,这种情况也是可以的,
原因是 只要 所连接的两个城市的人口如果特别大的话,A / B ,也满足题意。
那样的话,MST 在加入一条边就肯定成环,要使 A / B 最大,在A固定的情况下,B 最小就行啊,B = MST - 环中的边,现在转化成求这条最大的边。就是最小瓶颈路了,
问题就这样解决了,
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<iomanip>
using namespace std;
struct City
{
int x,y,p;
};
const int MAXN = 1010;
const int MAX = 0x3f3f3f3f;
City city[MAXN];
double _map[MAXN][MAXN];
double maxcost[MAXN][MAXN];
bool tag[MAXN];
double dis[MAXN];
bool used[MAXN][MAXN];
int father[MAXN];
int n;
double f(City a,City b)
{
double ans;
double x = a.x - b.x;
double y = a.y - b.y;
ans = sqrt(x * x + y * y);
return ans;
}
double prim()
{
double ans = 0;
memset(tag,0,sizeof(tag));
memset(used,0,sizeof(used));
memset(maxcost,0,sizeof(maxcost));
for(int i = 1; i<= n;++i)
{
dis[i] = _map[1][i];
father[i] = 1;
}
tag[1] = 1;
father[1] = 0;// 遗漏
for(int i = 1; i <= n - 1;++i)
{
int now = MAX;
double _min = MAX;
for(int j = 1; j <= n; ++j)
{
if(dis[j] < _min && !tag[j])
{
now = j;
_min = dis[j];
}
}
if(now == MAX)
return -1;
ans += _min;
tag[now] = 1;
used[father[now]][now] = used[now][father[now]] = 1; // 错误
for(int j = 1;j <= n; ++j)
{
if(tag[j] && j != now)
maxcost[now][j] = maxcost[j][now] = max(maxcost[father[now]][j],_min);
if(!tag[j] && dis[j] > _map[now][j])
{
dis[j] = _map[now][j];
father[j] = now;
}
}
}
return ans;
}
double smst()
{
double ans = -1,mst;
mst = prim();
for(int i = 1;i <= n - 1;++i)
{
for(int j = i + 1;j <= n; ++j)
{
if(used[i][j])
ans = max(ans,(city[i].p + city[j].p) * 1.0 / (mst - _map[i][j]));
else
ans = max(ans,(city[i].p + city[j].p) * 1.0 / (mst - maxcost[i][j]));
}
}
return ans;
}
int main()
{
int T;
ios::sync_with_stdio(false);
cin >> T;
while(T--)
{
cin >> n;
for(int i = 1;i <= n; ++i)
{
cin >> city[i].x >> city[i].y >>city[i].p;
}
for(int i = 1;i <= n; ++i)
{
for(int j = i + 1; j <= n; ++j)
{
_map[i][j] = _map[j][i] = f(city[i],city[j]);
}
}
double ans = smst();
cout << fixed << setprecision(2) << ans << endl;
}
return 0;
}