POJ 1611(并查集+知识)

并查集主要是两个过程,一个是并,一个是查

原理是用一个数组p[i]保存每个i的根节点,如果根节点一样则在同一个集合里,所以只有根节点p[i]=i;

查:

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

并:

void Union(int x,int y)

{

  int xx = find(x);int yy=find(y);

  if(xx!=yy)//不在一个集合里

    p[xx]=yy;

}

#include <cstdio>
#include <iostream>
#include <queue>
using namespace std;

#define sf scanf
#define pf printf
#define debug printf("!
")
#define blank printf("
")
#define mem(a,b) memset(a,b,sizeof(a))

const int MaxN = 30010;
const int INF = 1<<27;

int p[MaxN],a[MaxN];

int m,n;

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

void Union(int x,int y)
{
          int rx = find(x);
          int ry = find(y);
          p[rx] = ry;
}

int main()
{
    int i,j,k;
    while(~scanf("%d%d",&n,&m),n+m)
    {
        i = 0;
        mem(p,0);
        mem(a,0);
        for(j=0;j<n;j++)
                              p[j] = j;
        while(m--)
        {
                  sf("%d",&k);
                  for(i=0;i<k;i++)
                  {
                                        sf("%d",&a[i]);
                  }
                  for(i=1;i<k;i++)
                  {
                                        Union(a[i-1],a[i]);
                  }
        }
        int cnt = 0;
                    for(i = 0;i<n;i++)
                    {
                              if(find(i)==find(0))
                                        cnt++;
                    }
                    pf("%d
",cnt);
    }

    return 0;
}
原文地址:https://www.cnblogs.com/qlky/p/5154777.html