题意:给出n个城市的坐标和人口,两个间的距离是欧几里得距离,可以免距离连接一条路径,要是免费连的那两个城市的人口比上生成树的距离比值最大。。
次小生成树,先求出最小生成树,然后枚举生成树上每一条边,把他去掉,就形成来两个连通块,从两个连通块中分别找到人口最大的城市,免费连接起来,所以就是这两个人口加起来比上去掉一条边的最小生产数的权值,可以在求最小生成树时把生产树上的边存起来。。。
吐糟下。。。。用邻接表,不是MLE,就是RE(爆栈),弄得稀里糊涂,后来换成vector就变WA了。。。然后发现欧几里得距离居然弄成了曼哈顿距离。。。然后A了
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
const int MAXN=1010;
const int INF=1<<30;
double cost[MAXN][MAXN];
double lowcost[MAXN];
int pre[MAXN];
vector<int> G[MAXN];
struct Node
{
int x,y;
double val;
}p[MAXN];
double prim(int v0,int n)
{
int i,j;
double ans=0;
memset(pre,-1,sizeof(pre));
for(i=1;i<=n;i++)
{
lowcost[i]=cost[v0][i];
pre[i]=v0;
}
for(i=1;i<n;i++)
{
double mincost=(double)INF;
int minone=-1;
for(j=1;j<=n;j++)
{
if(lowcost[j]&&mincost>lowcost[j])
{
mincost=lowcost[j];
minone=j;
}
}
ans+=mincost;
G[pre[minone]].push_back(minone);
G[minone].push_back(pre[minone]);
lowcost[minone]=0;
for(j=1;j<=n;j++)
{
if(lowcost[j]>cost[minone][j])
{
lowcost[j]=cost[minone][j];
pre[j]=minone;
}
}
}
return ans;
}
double maxp;
void dfs(int u,int fa)
{
if(p[u].val>maxp)
maxp=p[u].val;
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(v==fa)
continue;
dfs(v,u);
}
}
double dist(Node a,Node b)
{
return sqrt(1.0*(a.x-b.x)*(a.x-b.x)+1.0*(a.y-b.y)*(a.y-b.y));
}
double solve(int n)
{
int i,j;
double mst=prim(1,n);
double ans=0;
for(i=1;i<=n;i++)
{
for(j=0;j<G[i].size();j++)
{
int v=G[i][j];
double temp=0;
maxp=0;
dfs(v,i);
temp+=maxp;
maxp=0;
dfs(i,v);
temp+=maxp;
ans=max(ans,temp*1.0/(mst-cost[i][v]));
}
}
return ans;
}
int main()
{
int t,n,i,j;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=1;i<=n;i++)
G[i].clear();
for(i=1;i<=n;i++)
scanf("%d%d%lf",&p[i].x,&p[i].y,&p[i].val);
for(i=1;i<=n;i++)
{
for(j=i+1;j<=n;j++)
cost[i][j]=cost[j][i]=dist(p[i],p[j]);
}
printf("%.2f\n",solve(n));
}
return 0;
}