带权并查集 学习笔记

例题

[NOI2002] 银河英雄传说
题目传送门

算法实现

我们发现操作只有合并没有分解,所以考虑并查集。
但是好像普通的并查集貌似解决不了,所以我们要使用带权并查集。
我们需要维护两个数组:v,w , vi 代表该节点以下的节点的个数, wi 代表该节点以上的节点个数。
显然,节点 i,j 的距离(保证在同一队)是 |vivj|
考虑如何进行路径压缩。
看代码吧

int getfa(int x){
if(x==f[x]) return x;
int tmp=f[x];//以防f[x]改变
f[x]=getfa(f[x]);
w[x]+=w[tmp];//更新w[x]
return f[x];
}

修改很简单,首先要把这条边接过去,然后处理上下的 wv 即可。

f[x]=y;
w[x]+=v[y];
v[y]+=v[x];

最后记得初始化

for(int i=1;i<=30000;i++) f[i]=i,v[i]=1,w[i]=0;

代码

已经进行防抄袭处理,删了几个地方

#include<cstdio>
#define abs(x) ((x)>0?(x):-(x))
#define maxn 30039
using namespace std;
//#define debug
typedef int Type;
inline Type read(){
Type sum=0;
int flag=0;
char c=getchar();
while((c<'0'||c>'9')&&c!='-') c=getchar();
if(c=='-') c=getchar(),flag=1;
while('0'<=c&&c<='9'){
sum=(sum<<1)+(sum<<3)+(c^48);
c=getchar();
}
if(flag) return -sum;
return sum;
}
char c;
int T,a,b,x,y;
int f[maxn],v[maxn],w[maxn];
int getfa(int x){
if(x==f[x]) return x;
int tmp=f[x];
f[x]=getfa(f[x]);
w[x]+=w[tmp];
return f[x];
}
int main(){
for(int i=1;i<=30000;i++) f[i]=i,v[i]=1,w[i]=0;
while(T--){
c=getchar(); while(c!='M'&&c!='C') c=getchar();
a=read(); b=read();
x=getfa(a); y=getfa(b);
if(c=='M'){
w[x]+=v[y];
v[y]+=v[x];
}
else{
if(x!=y) printf("-1\n");
else printf("%d\n",abs(w[a]-w[b])-1);
}
}
return 0;
}
posted @   jiangtaizhe001  阅读(35)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示