2 4 1 1 20 1 2 30 200 2 80 200 1 100 3 1 1 20 1 2 30 2 2 40
65.00 70.00
坐标系各点带权,求关于各点距离的最小生成树后,遍历所有边找满足题意的A/B,
即,
uv不属于MST时 A/B=max(A/B,(people(u)+people(v))/(ans-MAX[u][v]))
uv属于MST时 A/B=max(A/B,people(u)+people(v))/(ans-cost[u][v])
//#pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <stack> #include <map> #include <queue> #define INF 0x3f3f3f3f using namespace std; const int MAXN = 1005; double cost[MAXN][MAXN]; bool vis[MAXN]; bool in_MST[MAXN][MAXN]; double Max_e[MAXN][MAXN]; double lowcost[MAXN]; int pre[MAXN]; int m,n; struct Point { int x,y; int popu; } point[MAXN]; double Distance(Point a,Point b) { return sqrt((double)((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y))); } double prim() { double ans=0; memset(vis,0,sizeof(vis)); memset(Max_e,0,sizeof(Max_e)); memset(in_MST,0,sizeof(in_MST)); vis[0]=1; pre[0]=-1; for(int i=0; i<n; ++i) { lowcost[i]=cost[0][i]; pre[i]=0; } lowcost[0]=0; for(int i=1; i<n; ++i) { double minc=INF; int p=-1; for(int j=0; j<n; ++j) if(!vis[j] && minc>lowcost[j]) { minc=lowcost[j]; p=j; } if(minc==INF)return -1; ans+=minc; vis[p]=true; in_MST[p][ pre[p] ]=in_MST[ pre[p] ][p]=true; for(int j=0; j<n; ++j) { if(vis[j] && j!=p) Max_e[j][p]=Max_e[p][j]=max(Max_e[pre[p]][j],lowcost[p]); if(!vis[j]&&lowcost[j]>cost[p][j]) { lowcost[j]=cost[p][j]; pre[j]=p; } } } return ans; } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=0; i<n; ++i)cost[i][i]=0; for(int i=0; i<n; ++i) { scanf("%d%d%d",&point[i].x,&point[i].y,&point[i].popu); for(int j=0; j<i; ++j) cost[i][j]=cost[j][i]=Distance(point[i],point[j]); } double ans=prim(),temp; double Max=0; for(int i=0; i<n; ++i) for(int j=i+1; j<n; ++j) { double peo=point[i].popu+point[j].popu; if(in_MST[i][j]) { temp=peo/(ans-cost[i][j]); if(temp>Max) Max=temp; } else { temp=peo/(ans-Max_e[i][j]); if(temp>Max) Max=temp; } } printf("%0.2lf\n",Max); } return 0; }