【LA 5713 】 Qin Shi Huang's National Road System (MST)

【题意】

  秦始皇要在n个城市之间修路,而徐福声可以用法术位秦始皇免费修1条路,每个城市还有人口数,现要求徐福声所修之路的两城市的人口数之和A尽量大,而使n个城市互通需要修的路长B尽量短,从而使得A/B最大。问A/B最大是多少?(1000个城市)

Input
The first line contains an integer t meaning that there are t test cases (t ≤ 10).
For each test case:
The first line is an integer n meaning that there are n cities (2 < n ≤ 1000).
Then n lines follow. Each line contains three integers X, Y and P (0 ≤ X, Y ≤ 1000, 0 < P <
100000). (X, Y ) is the coordinate of a city and P is the population of that city.
It is guaranteed that each city has a distinct location.
Output
For each test case, print a line indicating the above mentioned maximum ratio A/B. The result should
be rounded to 2 digits after decimal point.
Sample Input
2
4
1 1 20
1 2 30
200 2 80
200 1 100
3
1 1 20
1 2 30
2 2 40
Sample Output
65.00
70.00

 

 

【分析】

  

  枚举法术边,然后目标就是剩下的路长度最小,并且要形成生成树。
  普通的做法就是每一次枚举都做一遍,那样就是n^3(排序可以只排一次)。但是其实可以预处理之后再求的。就是一条边置为0之后的最小生成树,这棵树与删边加一起一定构成一个环,我们用这条边代替一条边,必然选择这个环的最大边,预处理maxcost[u][v]表示u,v在生成树上的路径的最大边,然后直接求ans就好了啦~

 

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
#define Maxn 1100
#define Maxm 1000010

struct node
{
    int x,y,next;
    double c;
};
node t[Maxn*2],tt[Maxn],t2[Maxm];
int len,ln,n;

int first[Maxn],fa[Maxn];
double mc[Maxn][Maxn];
bool np[Maxn];

int myabs(int x) {return x<0?-x:x;}
// int mymax(int x,int y) {return x>y?x:y;}
double mymax(double x,double y) {return x>y?x:y;}

void ins(int x,int y,double c)
{
    t[++ln].x=x;t[ln].y=y;t[ln].c=c;
    t[ln].next=first[x];first[x]=ln;
}

bool cmp(node x,node y) {return x.c<y.c;}

int ffind(int x)
{
    if(fa[x]!=x) fa[x]=ffind(fa[x]);
    return fa[x];
}

void dfs(int x,int f,double l)
{
    for(int i=1;i<=n;i++) if(np[i])
      mc[i][x]=mc[x][i]=mymax(mc[i][f],l);
    np[x]=1;
    for(int i=first[x];i;i=t[i].next) if(t[i].y!=f)
      dfs(t[i].y,x,t[i].c);
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d%d%lf",&tt[i].x,&tt[i].y,&tt[i].c);
        len=0;
        for(int i=1;i<=n;i++)
         for(int j=i+1;j<=n;j++)
         {
             double nx=(double)(tt[i].x-tt[j].x),ny=(double)(tt[i].y-tt[j].y);
             t2[++len].x=i;t2[len].y=j;t2[len].c=sqrt(nx*nx+ny*ny);
            // ins(i,j,sqrt(nx*nx+ny*ny));
         }
        for(int i=1;i<=n;i++) fa[i]=i;
        double sum=0;
        ln=0;memset(first,0,sizeof(first));
        sort(t2+1,t2+1+len,cmp);
        for(int i=1;i<=len;i++)
        {
            if(ffind(t2[i].x)!=ffind(t2[i].y))
            {
                fa[ffind(t2[i].x)]=ffind(t2[i].y);
                ins(t2[i].x,t2[i].y,t2[i].c);ins(t2[i].y,t2[i].x,t2[i].c);
                sum+=t2[i].c;
            }
            if(ln==2*(n-1)) break;
        }
        memset(mc,0,sizeof(mc));
        memset(np,0,sizeof(np));
        dfs(1,0,0);
        double ans=0;
        for(int i=1;i<=len;i++)
        {
            double A=tt[t2[i].x].c+tt[t2[i].y].c;
            if(A*1.0/(sum-mc[t2[i].x][t2[i].y])>ans)
                ans=A*1.0/(sum-mc[t2[i].x][t2[i].y]);
        }
        printf("%.2lf\n",ans);
    }
    return 0;
}
View Code

 

2016-10-31 21:44:35

posted @ 2016-10-31 21:40  konjak魔芋  阅读(341)  评论(0编辑  收藏  举报