hdoj 4081 Qin Shi Huang's National Road System

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

 

解题报告:

先求最小生成树,并把这棵树记录下来,用low,和pre数组

然后dp数组表示最大边,这个信息可以在求prim的时候得到。

然后不断枚举任意两点修魔法路。那么这条路可能在最小生成树上,或者不在。

如果不在则替换到这两点之间的在mst上的最长路。dp数组

如果在咋直接替换到mst上的路 也是dp数组

View Code
#include<iostream>

#include<string.h>

#include<stdio.h>

#include<algorithm>

#include<cmath>

using namespace std;

#define maxn 1110

#define inf  ~0U>>1

double map[maxn][maxn];

double people[maxn];

double low[maxn];

double max(double a,double b)

{

    return a>b?a:b;

}

struct node0

{

    double x;

    double y;

}node[maxn];

double dp[maxn][maxn];

int n;

int visit[maxn];

int pre[maxn];

double sum;

double len(double x1,double y1,double x2,double y2)

{

    return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));

}

void init()

{

    memset(people,0,sizeof(people));

    for(int i=0;i<=maxn;i++)

    for(int j=0;j<=maxn;j++)

    map[i][j]=inf;

    scanf("%d",&n);

    for(int i=1;i<=n;i++)

    scanf("%lf%lf%lf",&node[i].x,&node[i].y,&people[i]);

}



void MAP()

{

       for(int i=1;i<n;i++)

        {

            for(int j=i+1;j<=n;j++)

            {

                map[i][j]=map[j][i]=len(node[i].x,node[i].y,node[j].x,node[j].y);

            }

        }

}



double prim()

{

    double temp;

    int id;

    double ans=0;

    memset(visit,0,sizeof(visit));

    memset(dp,0,sizeof(dp));

    for(int i=1;i<=n;i++)pre[i]=1;

    for(int i=1;i<=maxn;i++)low[i]=inf;

    visit[1]=1;

    for(int i=2;i<=n;i++)

        low[i]=map[1][i];

    for(int i=2;i<=n;i++)

    {

    temp=inf;

    for(int j=1;j<=n;j++)

        if(!visit[j]&&low[j]<temp)

    temp=low[j],id=j;

    ans+=temp,visit[id]=1;

    for(int j=1;j<=n;j++)

    if(visit[j]&&id!=j)

    dp[id][j]=dp[j][id]=max(dp[pre[id]][j],temp);



    for(int j=1;j<=n;j++)

        if(low[j]>map[id][j]&&!visit[j])

            low[j]=map[id][j],pre[j]=id;

    }

    return ans;

}

double  solve()

{

    double  temp=0.0;

    double ans=0.0;

    for(int i=1;i<n;i++)

    for(int j=i+1;j<=n;j++)

    {

       temp=(people[i]+people[j])/(sum-dp[i][j]);

       ans=max(temp,ans);

    }

    return ans;

}

int main()

{

    int test;

    for(cin>>test;test;test--)

    {

        init();

        MAP();

        sum=prim();

        printf("%.2f\n",solve());

    }

    return 0;

}

你可能感兴趣的:(System)