带权并查集 学习笔记
例题
[NOI2002] 银河英雄传说
题目传送门
算法实现
我们发现操作只有合并没有分解,所以考虑并查集。
但是好像普通的并查集貌似解决不了,所以我们要使用带权并查集。
我们需要维护两个数组: , 代表该节点以下的节点的个数, 代表该节点以上的节点个数。
显然,节点 的距离(保证在同一队)是
考虑如何进行路径压缩。
看代码吧
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]; }
修改很简单,首先要把这条边接过去,然后处理上下的 和 即可。
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; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· 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工具