带权并查集浅谈
笔者最近刷到了一道带权并查集的题目,当做入门博客写一篇学习笔记吧。
题目中要求求距离+换爹,很显然,暴力的dfs在20000的数据下绝对会被卡的。
自然想到,什么数据结构可以快速维护父子关系?
显然有并查集。
那么,我们要做的就是修改并查集,使它能够维护距离了。
那么,我们在每一次更新父亲(路径压缩)的时候更新距离。
先来看最基本的find函数:
inline int find(int x){ return x==f[x]?x:f[x]=find(f[x]); }
我们要在这时候维护距离dis的改变。
于是,我们先记录下路径压缩前的父亲。
然后压缩。
返回的时候,当前的结点要累加之前的距离即可。
代码:
inline int find(int x){ if(x==f[x])return x; int t=f[x];//记录之前父亲 f[x]=find(f[x]);//并查集find dis[x]+=dis[t];//累加距离 return f[x]; }
对于多组训我,切记清空数组。并查集的初始化不要忘记。
将dis数组初始化为0,f数组照常赋值成自己。
对于第一个操作,直接认爹,然后更新距离。
所以,对于第二个E操作,在询问的时候要find一下,以便于更新之前没有更新的距离。之后直接输出即可。
注意,dis[x]维护的是x到根的距离。
并查集是树形结构。
总代码:
#include<cstdio>//加权并查集 #include<iostream> #include<cstring> using namespace std; int dis[50000],f[50000]; int n,x,y,t; char s[50]; /*st struct node{ int next,to; }; head[5000]; inline void add(int x,int y){ e[++tot].to=y; e[tot].next=head[x]; head[x]=tot; }*/ inline int abs(int x){return x<0?-x:x;} inline void read(int &x){ int s=0,w=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-')w=-1; ch=getchar(); }while(ch>='0'&&ch<='9'){ s=(s<<1)+(s<<3)+(ch^48); ch=getchar(); }x=s*w; } inline int find(int x){ if(x==f[x])return x; int t=f[x];//记录之前父亲 f[x]=find(f[x]);//并查集find dis[x]+=dis[t];//累加距离 return f[x]; } inline void init(){ memset(dis,0,sizeof(dis)); for(int i=1;i<=n;++i)f[i]=i; } int main(){ read(t); while(t--){ read(n); init(); while(1){ cin>>s; if(s[0]=='O')break; if(s[0]=='I'){ read(x); read(y); f[x]=y; dis[x]+=abs(x-y)%1000; }else{ read(x); find(x); printf("%d\n",dis[x]); } } } return 0; }
留一道例题,笔者之后补题解。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· .NET Core 中如何实现缓存的预热?
· 三行代码完成国际化适配,妙~啊~
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?