HDU 4081 生成树

版权声明: 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;
}

猜你喜欢

转载自blog.csdn.net/nwpu2017300135/article/details/82466855