hdu 1875 畅通工程再续

 最小生成树的入门题,和普通裸题有些区别,需要做出一点修改

题目是要求两个岛的直接连线要大于等于10小于等于1000而不是说任意两个岛的路径和都是要满足这个条件,否则的话,要满足任意两个岛的路径和满足这个条件还是比较麻烦的

显然这道题用prim算法实现才好,因为最多有n*(n-1)/2条边用kruskal算法不好

在prim模板中要修改两个地方几个,一个是初始化

 

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

    {

        adj[i]=1;

        if(g[1][i]>=MIN) lowcoat[i]=g[1][i];

        else             lowcoat[i]=INF;

    }

    lowcoat[1]=0;

 

原本是直接lowcoat[i]=g[1][i]; 的。但是知道在prim算法中我们是不断更新lowcoat[i]使它的值不断变小的,所以lowcoat[i]只会越来越小,如果lowcoat[i]的值在初始化过程中就已经小于10,那么最后的构建结果中某条路径的长度一定小于10.

另外一个不同于模板的地方是

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

            if(lowcoat[i] && lowcoat[i]>g[k][i] && g[k][i]>=MIN)

            {

                lowcoat[i]=g[k][i];

                adj[i]=k;

            }

 

同样地,是为了避免在更新lowcoat[i]的时候使它的值小于10或大于1000,

 

for(sum=0,i=2; i<=n; i++)

    {

        if(g[i][adj[i]] < MIN || g[i][adj[i]]> MAX)  { sum=-1; break;}

        sum+=g[i][adj[i]];

    }

这个就是最后的判断,判断所有n-1条连线,然后看每条连线是否满足条件,只要有一条连线不满足条件,就说明构建失败

 

 

而有些小细节还是可以修改一下的,更新部分可以改为

 

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

 

            if(lowcoat[i] && lowcoat[i]>g[k][i] && g[k][i]>=MIN)

 

            {

 

                lowcoat[i]=g[k][i];

 

                adj[i]=k;

 

            }

 

最后判断是否构建成功部分可以改为

 

for(sum=0,i=2; i<=n; i++)

 

    {

 

        if(g[i][adj[i]]> MAX)  { sum=-1; break;}

 

        sum+=g[i][adj[i]];

 

    }

 

 

#include <stdio.h>

#include <string.h>

#include <math.h>

#define N 110

#define MIN 10

#define MAX 1000

#define INF 982382334

int n;

int x[N],y[N];

double g[N][N];



double dis(int i , int j)

{ return sqrt( 1.0*((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])) ); }



void input()

{

    int i,j;

    scanf("%d",&n);

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

        scanf("%d%d",&x[i],&y[i]);



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

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

            g[i][j]=g[j][i]=dis(i,j);

    return ;

}

void print_graph()

{

    int i,j;

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

    {

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

            printf("%.1lf ",g[i][j]);

        printf("\n");

    }

}



void prim()

{

    double lowcoat[N],min,sum;

    int adj[N];

    int v,i,j,k;



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

    {

        adj[i]=1;

        if(g[1][i]>=MIN) lowcoat[i]=g[1][i];

        else             lowcoat[i]=INF;

    }

    lowcoat[1]=0;



    for(v=1; v<n; v++)  //还要纳入n-1个点

    {

        min=INF; k=1;

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

            if(lowcoat[i] && lowcoat[i]<min)

            { min=lowcoat[i]; k=i;}



        lowcoat[k]=0;



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

            if(lowcoat[i] && lowcoat[i]>g[k][i] && g[k][i]>=MIN)

            {

                lowcoat[i]=g[k][i];

                adj[i]=k;

            }

    }



    for(sum=0,i=2; i<=n; i++)

    { 

        if(g[i][adj[i]] < MIN || g[i][adj[i]]> MAX)  { sum=-1; break;}

        sum+=g[i][adj[i]];

    }

    if(sum==-1)  printf("oh!\n");

    else

    {

        sum*=100;

        printf("%.1lf\n",sum);

    }

    return ;

}



int main()

{

    int T;

    double ans;

    scanf("%d",&T);

    while(T--)

    {

        input();

//        print_graph();

        prim();

    }

    return 0;

}

 

 

你可能感兴趣的:(HDU)