版权声明: https://blog.csdn.net/nwpu2017300135/article/details/82466855
http://acm.hdu.edu.cn/showproblem.php?pid=4081
题意:给定点坐标求最小生成树,可以让一条路距离变为0,现在要使得选择的这条路端点点权之和/这条路为0的最小生成树边权之和的值最大。
题解:求次小生成树后产生数组length[x][y]表示从x到y走最小生成树途中经过的最长的一条边。然后枚举每条边,就可以了。
代码:
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn = 1005;
const int maxm= 1000005;
int p[maxn];
int finde(int x){
if(p[x]==x)return x;
return p[x]=finde(p[x]);
}
bool issame(int x,int y){
x=finde(x);
y=finde(y);
return x==y;
}
void join(int x,int y){
x=finde(x);
y=finde(y);
p[x]=y;
}
struct node{
int a,b,w;
bool select;
}e[maxm];
bool cmp(node a,node b){
return a.w<b.w;
}
struct node1{
int to,next;
};
node1 link[maxn];
int il;
int head[maxn];
int iend[maxn];
int length[maxn][maxn];
int n,m;
void kruskal(){
int k=0;
int i,x,y;
int w,v;
//for(i=1;i<=n;i++)p[i]=i;
for(il=0;il<=n;il++){
link[il].to=il+1;
link[il].next=head[il+1];
iend[il+1]=il;
head[il+1]=il;
}
sort(e,e+m,cmp);
for(i=0;i<m;i++){
if(k==n-1)break;
if(e[i].w<0)continue;
x=finde(e[i].a);
y=finde(e[i].b);
if(x!=y){
for(w=head[x];w!=-1;w=link[w].next){
for(v=head[y];v!=-1;v=link[v].next){
length[link[w].to][link[v].to]=length[link[v].to][link[w].to]=e[i].w;
}
}
link[iend[y]].next=head[x];
iend[y]=iend[x];
join(x,y);
k++;
e[i].select=true;
}
}
return ;
}
void init(){
int i;
for(i=1;i<=n;i++)p[i]=i;
memset(head,-1,sizeof(head));
memset(length,0,sizeof(length));
//memset(e,0,sizeof(e));
}
/////////////////
int x[maxn],y[maxn],r[maxn];
int len(int a,int b){
int res=(x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]);
return res;
}
double getans1(node e,double mst){
double totp=r[e.a]+r[e.b];
return totp/(mst-sqrt(length[e.a][e.b]));
}
double getans2(node e,double mst){
double totp=r[e.a]+r[e.b];
return totp/(mst-sqrt(e.w));
}
int main()
{
int t,i,tot,j;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
init();
for(i=1;i<=n;i++){
scanf("%d%d%d",&x[i],&y[i],&r[i]);
}
tot=0;
for(i=1;i<=n;i++){
for(j=i+1;j<=n;j++){
e[tot].a=i;
e[tot].b=j;
e[tot].w=len(i,j);
e[tot].select=false;
tot++;
}
}
m=tot;
kruskal();
double mst=0;
double ans=0;
for(i=0;i<m;i++)if(e[i].select)mst+=sqrt(e[i].w);
for(i=0;i<m;i++){
if(e[i].select)ans=max(ans,getans2(e[i],mst));
else ans=max(ans,getans1(e[i],mst));
}
//printf("%.2f\n",mst);
printf("%.2f\n",ans);
}
//cout << "Hello world!" << endl;
return 0;
}