zoukankan      html  css  js  c++  java
  • 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;
    }

     

  • 相关阅读:
    matlab cell
    matlab linux 快捷键设置——有问题还是要解决
    latex 小结
    TOJ 1258 Very Simple Counting
    TOJ 2888 Pearls
    HDU 1248 寒冰王座
    TOJ 3486 Divisibility
    TOJ 3635 过山车
    TOJ 1840 Jack Straws
    HDU 4460 Friend Chains
  • 原文地址:https://www.cnblogs.com/scau20110726/p/2729776.html
Copyright © 2011-2022 走看看