关于并查集的优化
并查集有两种优化方式:
第一个是路径压缩,这个保证每个点查询之后能够做到路径上节点
但是路径压缩破坏了树形结构,所以这时我们找不到这个点是由哪个集合得来.
所以就有另一种优化方法,按秩合并并查集.
解释一下,秩就是并查集的深度.
我们每一次将深度较小者并到深度较大者,在二者深度相同时,整个并查集的秩增加.
这个时候就成功维护出了一个
两者代码实现均不难,不加多余解释.
这里不再放路径压缩并查集例题了,之前整理过类似例题.
例题:按秩合并
这个题是可以将每个
因为一个边的两端节点只能选一个,所以维护一个size与edge数.
这两者取min为一个联通图可以贡献的答案.
用dep实现按秩合并,保证查询的深度不炸,然后每次将一个新点对应值并入集合,dfs后撤销操作.
每个点加入后统计答案即可.
update: 按秩合并可以直接用size来实现,这个也是满足深度性质的,自己手搓一下就知道了。
#include<bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;
#define qr qr()
#define ps push_back
#define ve vector<int>
using namespace std;
const int N=2e5+200;
int n,m,a[N],b[N],f[N],sz[N],ed[N],dep[N],ans[N];
ve e[N];
inline ll qr{
ll x=0;char ch=getchar();bool f=0;
while(ch>57||ch<48)f=(ch=='-')?1:0,ch=getchar();
while(ch>=48&&ch<=57)x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return f?-x:x;
}
int find(int now){
return (f[now]==now)?now:find(f[now]);
}
void dfs(int now,int fa){
// cout<<now<<' '<<fa<<endl;
int x=find(a[now]),y=find(b[now]);
if(dep[x]<dep[y])swap(x,y);
ans[now]=ans[fa];
ans[now]-=min(sz[x],ed[x]);
int tmp=dep[x];
if(x^y){
ans[now]-=min(sz[y],ed[y]);
sz[x]+=sz[y];
ed[x]+=ed[y];
f[y]=x;
dep[x]+=(dep[x]==dep[y]);
}
++ed[x];
ans[now]+=min(ed[x],sz[x]);
for(auto to:e[now])
if(to^fa)dfs(to,now);
--ed[x];
if(x^y){
sz[x]-=sz[y];
ed[x]-=ed[y];
f[y]=y;
dep[x]=tmp;
}
}
void init(){
n=qr;
for(int i=1;i<=n;++i){
a[i]=qr,b[i]=qr;
f[i]=i;sz[i]=1;dep[i]=1;
}
int f,t;
for(int i=1;i<n;++i){
f=qr,t=qr;
e[f].ps(t);e[t].ps(f);
}dfs(1,0);
for(int i=2;i<=n;++i)
printf("%d ",ans[i]);
}
int main(){
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
// ios::sync_with_stdio(0);
// cin.tie(0);
// cout.tie(0);
init();
return 0;
}
https://www.cnblogs.com/shining-like-stars
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现