hdu 4081Qin Shi Huang's National Road System(最小生成树变形)

 

 

http://acm.hdu.edu.cn/showproblem.php?pid=4081

 

 

题目大意:

            秦始皇要修建最小费用的道路,有个道士可以建一条免费魔法道路,但是道士要求这条道路连接的两个城市的人口要最多,秦始皇不同意,权衡之下决定用A/B的最大比值来修建魔法道路。

           A:魔法道路连接的城市总人口

           B:除魔法道路外需要修建的道路总长

           先生成一棵最小生成树,枚举每条边(在A一定的情况下,B越小,A/B越大),若这条边在树上,减去这条边的权值,否则减去成环最大边的权值。

 

 

 

#include<iostream>
#include<cstring>
#include<queue>
#include<cmath>
#include<cstdio>
using namespace std;
#define N 1001
double INF=99999999.0;
double map[N][N],low[N],max1[N][N];
int p[N],path[N][N];
void prim(int n)
{
	int i,j,vis[N],pos,now[N];
	double min,sum=0,max=0;
	for(i=0;i<n;i++)
	{
		low[i]=map[0][i];
		vis[i]=0;
		now[i]=0;
	}
	vis[0]=1;
	memset(max1,0,sizeof(max1));
	memset(path,0,sizeof(path));
	for(i=0;i<n;i++)
	{
		min=INF;
		pos=-1;
		for(j=0;j<n;j++)
			if(!vis[j]&&low[j]<min)
			{
				min=low[j];
				pos=j;
			}
			if(pos==-1)
				break;
			vis[pos]=1;
			path[now[pos]][pos]=path[pos][now[pos]]=1;//保存在树上的边,pos连接的边用now[]来保存
			sum+=min;
			for(j=0;j<n;j++)//次小生成树的枚举
				if(vis[j]&&j!=pos)
					max1[pos][j]=max1[j][pos]=max1[j][now[pos]]>low[pos]?max1[j][now[pos]]:low[pos];
			for(j=0;j<n;j++)
				if(low[j]>map[pos][j])
				{
					low[j]=map[pos][j];
					now[j]=pos;
				}
	}
	for(i=0;i<n;i++)
		for(j=0;j<n;j++)
		{
			if(i!=j)
			{
				if(path[i][j]==1)
				{
					if((p[i]+p[j])/(sum-map[i][j])>max)
						max=(p[i]+p[j])/(sum-map[i][j]);
				}
				else
				{
					if((p[i]+p[j])/(sum-max1[i][j])>max)
						max=(p[i]+p[j])/(sum-max1[i][j]);
				}
			}
		}
	printf("%.2lf\n",max);
}
int main()
{
	int t,n,i,x[N],y[N],j;
	cin>>t;
	while(t--)
	{
		cin>>n;
		for(i=0;i<n;i++)
			cin>>x[i]>>y[i]>>p[i];
		for(i=0;i<n;i++)
			for(j=0;j<n;j++)
			{
				if(i==j)
					map[i][j]=INF;
				else
					map[i][j]=sqrt((double)(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
			}
			prim(n);
	}
	return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值