并查集---模板

主要操作

初始化
把每个点所在集合初始化为其自身。
通常来说,这个步骤在每次使用该数据结构时只需要执行一次,无论何种实现方式,时间复杂度均为O(N)。
查找
查找元素所在的集合,即根节点。
合并
将两个元素所在的根节点相同,集合合并为一个集合,根节点不同就新建一个集合。
通常来说,合并之前,应先判断两个元素是否属于同一集合,这可用上面的“查找”操作实现
 
 
注意:要看题意编号是从0开始还是从1开始,模板是从1开始
 
模板一:不进行路径压缩,当前元素的根节点就是它的上一级
 
int p[1000005], r[1000005];
int n,t=0;
void init()//初始化集合,每个元素的老板都是自己
{
    for (int i = 1; i <= n; i++)
    {
        p[i] = i;
    }
}

int find(int x)                        //查找x的掌门
{
    int r=x;                           //委托 r 去找掌门
    while(p[r] != r)                 //如果r的上级不是r自己(也就是说找到的大侠他不是掌门 = =)
        r = p[r] ;                   // r 接着找他的上级,直到找到掌门为止。
    return  r ;                        //掌门驾到~~~
}


void join(int x,int y)                     //我想让虚竹和周芷若做朋友
{
    int xRoot=find(x), yRoot=find(y);             //虚竹的老大是玄慈,芷若MM的老大是灭绝
    if(xRoot != yRoot)                             //玄慈和灭绝显然不是同一个人
        p[xRoot]=yRoot;                       //方丈只好委委屈屈地当了师太的手下啦
}

void num()//求不同子集个数
{
    for(int i=1;i<=n;i++)//有多少个p[i]==i,就有多少个子集
    {
        if(p[i]==i)
            t++;
    }
}
bool sameRoot(int x, int y)//查询两个元素的老板是否相同
{
    return find(x) == find(y);
}

 

 模板二:进行路径压缩,当前元素的上级直接就是根节点
 
 
int p[1000005], r[1000005];
int n,t=0,cnt;
void init()//初始化集合,每个元素的老板都是自己
{
    for (int i = 1; i <= n; i++)
    {
        p[i] = i;
    }
}

int find(int x)//查找元素x的老板是谁
{
    if (x == p[x])
        return x;
    else
        return p[x] = find(p[x]);
}

void join(int x, int y)//合并两个集合
{
    int xRoot = find(x);
    int yRoot = find(y);

    if (xRoot == yRoot) //老板相同,不合并
        return;
    //cnt=cnt-1;
    if (r[xRoot] < r[yRoot]) //r[i]是元素i所在树的高度,矮树的根节点认高树的根节点做老板
        p[xRoot] = yRoot;
    else if (r[xRoot] > r[yRoot])
        p[yRoot] = xRoot;
    else
    {
        p[yRoot] = xRoot;//树高相同,做老板的树高度要加一
        r[xRoot]++;
    }
}
void num()//求不同子集个数
{
    for(int i=1;i<=n;i++)//有多少个p[i]==i,就有多少个子集
    {
        if(p[i]==i)
            t++;
    }
}
bool sameRoot(int x, int y)//查询两个元素的老板是否相同
{
    return find(x) == find(y);
}
//这里也可以用cnt求不同子集个数,初始化cnt=n,每加入一条边,cnt=cnt-1;

 

posted @ 2019-04-15 21:25  知道了呀~  阅读(232)  评论(0编辑  收藏  举报