为什么我进行实际测试,发现二者效率差不多。但是理论上 路径压缩+按秩合并复杂度为 O(n) 带个常数 4,路径压缩并查集时间复杂度 O(nlogn)。
代码:
按秩合并(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=106,后五个测试点 n=106,m=107
测试结果: