hdu 1233 还是畅通工程

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


这个题我用的贪心和并查集来解决的。 (kruskal算法)
首先用贪心对长度排序,然后按照长度从小到大选择连接,没有被联通的则直接连,要注意一个问题就是如果4个村庄是1 4联通了, 2 3联通了,那么肯定还要让这两个集合联通(用并查集)。
因此我用了一个p来表示不同的集合。

AC代码:
#include<iostream>

#include<cstdio>

#include<algorithm>

#include<cstring>



using namespace std;



struct Node

{

    int a,b;

    int l;

}a[5010];



bool cmp(Node a, Node b)

{

    return a.l < b.l;

}



int main()

{

    int n,i,j,sum,p,t;

    int b[110];       //记录这个村庄是否已经联通

    while(scanf("%d",&n)&&n)

    {

        sum = 0;                  //初始化总费用

        memset(b,0,sizeof(b));    //初始化所有村庄不连通

        for(i = 0; i < n*(n-1)/2; i++)

        {

            scanf("%d%d%d",&a[i].a,&a[i].b,&a[i].l);

        }

        sort(a,a+n*(n-1)/2,cmp); //权值从小到大排序

        p = 1;

        for(i = 0; i < n*(n-1)/2; i++)

        {

            if(b[a[i].a] == 0 || b[a[i].b] == 0)

            {

                sum += a[i].l;

                if(b[a[i].a] == 0 && b[a[i].b] == 0) //如果两个都没有被联通过,则为新联通图集合

                {

                    b[a[i].a] = b[a[i].b] = p;

                    p++;

                }

                else

                {

                    if(b[a[i].a] != 0)

                    {

                        b[a[i].b] = b[a[i].a];

                    }

                    else

                    {

                        b[a[i].a] = b[a[i].b];

                    }

                }

            if(b[a[i].a] != b[a[i].b])   //连个村庄在两个图的时候

            {

                t = b[a[i].b];

                sum += a[i].l;

                for(j = 1; j <= n; j++) //两集合合并

                {

                    if(b[j] == t)

                    {

                        b[j] = b[a[i].a];

                    }

                }

            }



        }

        printf("%d\n",sum);

    }



    return 0;

}



 

你可能感兴趣的:(HDU)