题目链接:点击打开链接
题意:n个城市,需要修建一些道路使得任意两个城市联通,还可以修一条魔法道路, 不花钱, 设魔法路连接的城市的人口之和为A, 所有道路总长为B, 求A/B的最大值。
思路: 次小生成树。 先做一次最小生成树, 然后用dfs搜索出最小生成树上任意两点之间最长的道路长度。 然后枚举在哪两个城市之间建魔法道路。n^2复杂度。
细节参见代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int mod = 1000000000 + 7;
const int INF = 1000000000;
const int maxn = 1000 + 10;
int T,n,m,cnt,p[maxn];
double val[maxn][maxn],d[maxn][maxn];
bool vis[maxn];
struct node {
double x, y, p;
}a[maxn];
struct Edge {
int a, b;
double c;
Edge(int a=0,int b=0,double c=0):a(a), b(b), c(c) {}
bool operator < (const Edge& rhs) const {
return c < rhs.c;
}
}edges[maxn*maxn];
vector<int> g[maxn];
int _find(int x) { return p[x] == x ? x : p[x] = _find(p[x]); }
void dfs(int root, int cur) {
vis[cur] = true;
int len = g[cur].size();
for(int i=0;i<len;i++) {
int v = g[cur][i];
if(!vis[v]) {
val[root][v] = max(val[root][cur], d[cur][v]);
dfs(root, v);
}
}
}
double solve() {
sort(edges, edges + cnt);
for(int i=1;i<=n;i++) p[i] = i, g[i].clear();
double minv = 0;
for(int i=0;i<cnt;i++) {
int x = _find(edges[i].a);
int y = _find(edges[i].b);
if(x != y) {
p[x] = y;
g[edges[i].a].push_back(edges[i].b);
g[edges[i].b].push_back(edges[i].a);
d[edges[i].a][edges[i].b] = d[edges[i].b][edges[i].a] = edges[i].c;
minv += edges[i].c;
}
}
for(int i=1;i<=n;i++) {
memset(vis, false, sizeof(vis));
dfs(i, i);
}
double ans = 0;
for(int i=1;i<=n;i++) {
for(int j=i+1;j<=n;j++) {
double A = a[i].p + a[j].p;
double B = minv - val[i][j];
ans = max(ans, A/B);
}
}
return ans;
}
int main() {
scanf("%d",&T);
while(T--) {
scanf("%d",&n);
for(int i=1;i<=n;i++) {
scanf("%lf%lf%lf",&a[i].x,&a[i].y,&a[i].p);
}
cnt = 0;
for(int i=1;i<=n;i++) {
for(int j=i+1;j<=n;j++) {
double dist = sqrt((a[i].x-a[j].x)*(a[i].x-a[j].x) + (a[i].y-a[j].y)*(a[i].y-a[j].y));
edges[cnt++] = Edge(i, j, dist);
}
}
printf("%.2f\n",solve());
}
return 0;
}