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;
}

 

 

posted @ 2012-10-18 17:01  Titanium  阅读(1082)  评论(0编辑  收藏  举报