hdu 1232 畅通工程

2012-11-23

今天复习了一下并查集,然后这道题才发现当时是傻掉了,其实就是并查集找有多少个连通分量,有c个连通分量的话要把他们连起来就需要c-1条边,根本不需要kruskal算法…………………………

#include <cstdio>

#include <cstring>

#define N 1010

int p[N];

int n,m;



int find(int x)

{  return p[x]==x ? x : p[x]=find(p[x]);  }

int main()

{

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

    {

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

            p[i]=i;

        scanf("%d",&m);

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

        {

            int u,v,x,y;

            scanf("%d%d",&u,&v);

            x=find(u);

            y=find(v);

            if(x!=y)

                p[x]=y;

        }

        int count=0;

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

            if(p[i]==i)

                count++;

        printf("%d\n",count-1);

    }

    return 0;

}

 

 

 

//最小生成树裸题

//给出已经存在的边(输入中可能重复但是不影响),然后问你要构建出最小生成树还需要//多少条边

//用kruskal算法显然更合理并且方便,已经存在的边保存在边集数组中,然后看看这些已

//经存在的边有多少条是可以纳入的(因为已经存在的边如果全部纳入的话可能有环)

//没纳入一条边我们就在count中计数,扫描完边集数组后,就可以已经纳入了多少条边

//即count,然后还需要的边就是n-1-count,因为由最小生成树的性质可知边数一定是n-1

//题目很容易,不要进去惯性思维与权值扯上关系,这道题与权值无关,其实是考察了最小//生成树成环的问题,边集数组中只需要保存边的两个点即可,不需要知道权值

 

 

#include <stdio.h>

#include <string.h>

#define MAX 1100

struct edge

{

    int b,e;

}a[MAX*MAX];

int count,n,m;

int p[MAX];



int find(int x)

{  return p[x]==x ? x : p[x]=find(p[x]) ;  }



int main()

{

    int i,j,x,y;

    while(scanf("%d",&n)!=EOF && n)

    {

        scanf("%d",&m);

        for(i=1; i<=m; i++) scanf("%d%d",&a[i].b,&a[i].e);



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



        for(count=0,i=1; i<=m; i++)

        {

            x=find(a[i].b);

            y=find(a[i].e);

            if(x!=y)

            {

                p[x]=y;

                count++;

            }

        }



        printf("%d\n",n-1-count);

    }

    return 0;

}

你可能感兴趣的:(HDU)