关于路径压缩、按秩合并并查集
  • 板块学术版
  • 楼主郑朝曦zzx
  • 当前回复3
  • 已保存回复3
  • 发布时间2022/11/28 12:48
  • 上次更新2023/10/27 01:07:00
查看原帖
关于路径压缩、按秩合并并查集
425694
郑朝曦zzx楼主2022/11/28 12:48

为什么我进行实际测试,发现二者效率差不多。但是理论上 路径压缩+按秩合并复杂度为 O(n)O(n) 带个常数 4,路径压缩并查集时间复杂度 O(nlogn)O(n\log n)

代码:

按秩合并(size)+路径压缩 (别人的代码)

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
int n,m;
struct bcj{
    int fa[maxn],g[maxn];
    void init(){
        for(int i=1;i<=n;++i)
            fa[i]=i,g[i]=1;
    }
    int find(int x){return fa[x]==x?fa[x]:fa[x]=find(fa[x]);}
    void merge(int x,int y){
        int u=find(x);
        int v=find(y);
        if(u==v) return;
        if(g[u]<g[v]) swap(u,v);
        fa[v]=fa[u];
        g[u]+=g[v];
    }
    bool check(int u,int v){return find(u)==find(v);}
}b;
signed main(){
    scanf("%d%d",&n,&m);
    b.init();
    while(m--){
        int op,u,v;
        scanf("%d%d%d",&op,&u,&v);
        if(op==1)
            b.merge(u,v);
        else
            putchar(b.check(u,v)?'Y':'N'),putchar('\n');
    }
    return 0;
}

按秩合并(dep):

#include <cstdio>
const int mxn = 1000010;
int n, m;
struct dsu
{
	int fa[mxn], dep[mxn];
	void init()
	{
		for (int i = 1; i <= n; ++i)
			fa[i] = i;
	}
	int find(int x)
	{
		if (fa[x] == x) return x;
		return fa[x] = find(fa[x]);
	}
	void merge(int x, int y)
	{
		int fx = find(x), fy = find(y);
		if (fx != fy)
		{
			if (dep[fx] > dep[fy]) fa[fy] = fx;
			else
			{
				if (dep[fx] == dep[fy]) dep[fx]++;
				fa[fx] = fy;
			}
		}
	}
}data;
int main()
{
	scanf("%d %d", &n, &m);
	data.init();
	while (m--)
	{
		int opt, x, y;
		scanf("%d %d %d", &opt, &x, &y);
		if (opt == 1) data.merge(x, y);
		else printf("%c\n", data.find(x) == data.find(y) ? 'Y' : 'N');
	}
	return 0;
}

路径压缩:

#include <cstdio>
int n, m;
int father[1000000];
int find(int k)
{
	if (father[k] == k) return k;
	else
	{
		father[k] = find(father[k]);
		return father[k];
	}
}
void q(int x, int y)
{
	father[find(y)] = find(x);
	return;
}
int main()
{
	scanf("%d %d", &n, &m);
	for (int i = 1; i <= n; i++)
		father[i] = i;
	for (int i = 1; i <= m; i++)
	{
		int x, y, z;
		scanf("%d %d %d", &x, &y, &z);
		if (x == 1)	q(y, z);
		else
		{
			if (find(y) == find(z)) printf("Y\n");
			else printf("N\n");
		}
	}
	return 0;
}

数据范围:前五个测试点 n=105,m=106n = 10^5, m = 10^6,后五个测试点 n=106,m=107n = 10^6, m = 10 ^ 7

测试结果:

2022/11/28 12:48
加载中...