并查集板子

操作:

1. 查询a与b是否属于同一集合

2. 合并a与b所在的集合

 

复杂度:

均摊复杂度优于O(log(n))

 

代码:(改了码风有点不习惯qaq

int f[maxn],h[maxn];//每个结点的父亲及树高

//初始化n个元素
void init(int n)
{
    for(int i = 1; i <= n; ++i)
    {
        f[i] = i;
        h[i] = 0;
    }
}

//查询树的根
int find(int x)
{
    if(f[x] == x) return x;
    else return f[x] = find(f[x]);//路径压缩
}

//合并x和y所属的集合
void unite(int x, int y)
{
    x = find(x);
    y = find(y);
    if(x == y) return;
    //树高优化,由于find后已经路径压缩,所以x与y的高度差最多为1
    if(h[x] < h[y]) f[x] = y;//这里树高相差1(一个为1,一个为0),合并后x与y的高度都不变
    else
    {
        f[y] = x;
        if(h[x] == h[y]) h[x]++;//这里树高相等,合并后父亲高度加1
    }
}

 

简化版:

int f[maxn];//每个结点的父亲

//初始化n个元素
void init(int n)
{
    for(int i = 1; i <= n; ++i)
        f[i] = i;
}

//查询树的根
int find(int x)
{
    if(f[x] == x) return x;
    return f[x] = find(f[x]);//路径压缩
}

//合并x和y所属的集合
void unite(int x, int y)
{
    x = find(x);
    y = find(y);
    f[x] = y;
}

 

posted @ 2020-10-05 10:46  .Ivorelectra  阅读(168)  评论(0编辑  收藏  举报