并查集(空间O(n),时间O(1))

算法讲解:

http://blog.csdn.net/dellaserss/article/details/7724401
https://segmentfault.com/a/1190000004023326 (详解)
下面的代码是 HDU1232

#include
#include
#include
#include
#include
using namespace std;


const int MAXN = 1e9+7;


const int Normal = 1050;
// 结构体的话 把数组类型一起放到一个结构体 就行


int parent[Normal];     // 存储根节点
int Rank[Normal];       // 存储集合的深度 ,方便合并操作
int ans;
void UFset()        // 初始化
{
    for(int i = 0;i < Normal;i++) {
        parent[i] = i;
        Rank[i] = 0;
    }
}


int Find(int x)     // 查找X的根节点
{
    int r = x;
    while(parent[r] != r)
    {
        r = parent[r];
    }
    while(x != r)   // 把路径上的所有点 都指向 一个根节点
    {
        int j = parent[x];
        parent[x] = r;
        x = j;
    }
    return r;
}


void Union(int x,int y) // 判断 x和y 是否联通 若不连通则合并
{
    int a = Find(x);
    int b = Find(y);
    if(a == b) return ;
    ans--;
    if(Rank[a] > Rank[b]) parent[b] = parent[a];
    else{
        if(Rank[a] == Rank[b]) Rank[b]++;
        parent[a] = parent[b];
    }
}


int main()
{
    int N,M;
    while(scanf("%d",&N) != EOF && N)
    {
        ans = N-1;
        scanf("%d",&M);
        UFset();
        for(int i = 1;i <= M;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            Union(a,b);
        }
        printf("%d\n",ans);
    }


    return 0;
}

你可能感兴趣的:(不知道什么分类)