题目链接:点击打开链接
题意: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; }