您的位置:首页 > 其它

HDU 4081 Qin Shi Huang's National Road System

2013-11-09 20:39 381 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4081

题意 :给定 二维坐标系上的N个点, 要建n-1条路, 每个点有一个坐标,代表这个城市的位置,每个点有一个人口值。现在可以在n-1条边中选一条 magic road. 修建这条magic
road不需代价。
现在求 求修建n-1条路 在这n个点中,使A/B最大 (A 代表magic road 路两端的城市 人口之和, B代表n-1条路中除了magic road外的其余的长度和)。
先求 按照 路的长度 的最小生成树, 显然,除去 特殊的magic road外的n-2 条边都是MST上的边,因为 如果magic road在生成树上 则去掉这条边, 不在的话,则 magic road 和MST成环  ,需要把环上的最长的边去掉。 这才能保证 B  最小。
则 必须去掉一条 MST的边,枚举每一条 MST的边,假设 这个边是去掉的 ,则求MST去掉这条边后的 两个连通分量 分别的 每个分量上的 点的人口的最大值 a  和 b。
枚举n-1次 求出 其中的最大值。
感觉或者可以: 枚举 生成树 上的两点,即:magic road的 两端 人口值确定,接下来 求出 添上这个便后 如果成环 则求环上的MST的最大值的边,不成环 就是去掉这条边,求这些枚举值中的最大值。
code:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define INF 1000000000
#define N 1003
int n,t,used
,tot,hh
,mm;
double d

,dis
;
struct no
{
int x,y,p;
}poi
;
struct node
{
int u,v,next;
double w;
}edge[2*N],edge1
;
double di(int x1,int x2)
{
int xx1=abs(poi[x1].x-poi[x2].x),xx2=abs(poi[x1].y-poi[x2].y);
return sqrt((double)(xx1*xx1+xx2*xx2));
}
void add(int u,int v,double w)
{
edge[tot].u=u; edge[tot].v=v;
edge[tot].w=w; edge[tot].next=hh[u];
hh[u]=tot++;
}
double prim(int u)
{
double sum=0;
for(int i=1;i<=n;i++)
dis[i]=d[u][i],used[i]=u;
used[u]=-1;
for(int i=1;i<n;i++)
{
int ar=-1;
double mi=INF;
for(int j=1;j<=n;j++)
{
if(used[j]>=0 && dis[j]<mi)
{
mi=dis[j]; ar=j;
}
}
sum+=mi;
add(ar,used[ar],mi);  add(used[ar],ar,mi);
edge1[i].u=used[ar];
edge1[i].v=ar;
edge1[i].w=mi;
used[ar]=-1;
for(int j=1;j<=n;j++)
if(used[j]>=0 && dis[j]>d[ar][j])
{
used[j]=ar;
dis[j]=d[ar][j];
}
}
return sum;
}
void dfs(int u,int p)
{
mm=max(mm,poi[u].p);
for(int i=hh[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(v==p) continue;
dfs(v,u);
}
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d%d%d",&poi[i].x,&poi[i].y,&poi[i].p);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
if(i==j) d[i][j]=INF;
else  d[i][j]=d[j][i]=di(i,j);
}
tot=0; memset(hh,-1,sizeof(hh));
double tmp=prim(1);
double ans=-INF;
for(int i=1;i<n;i++)
{
int m1,m2;
mm=-INF;
dfs(edge1[i].u,edge1[i].v);
m1=mm;
mm=-INF;
dfs(edge1[i].v,edge1[i].u);
m2=mm;
ans=max(ans,(double)(m1+m2)/(tmp-edge1[i].w));
}
printf("%.2f\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: