并查集学习总结
并查集作用:判断两个元素是否在一个集合内。
方式:通过记录每个元素对应的par[x]值来判断,如果两者相等,则为同组,否则为不同组。
_rank[maxn]的作用:_rank[i]记录的是每一个节点所在的树的高度,查询的时候意义不大,但是当两棵树合并的时候,当树的高度小的树连接到树的高度高的树会让树的整体高度较小,而保证查询优化。
状态压缩:并查集的状态压缩通过如下代码实现:
int find(int x){ if(par[x]==x) return x; }else{ return par[x]=find(par[x]); } }
上面的代码可以让所有的节点都直接连到根节点上,这样无论原本的树高度为多少,在这样一次操作后,树的高度都为2。所以在有状态压缩的情况下,_rank的作用非常小,几乎可以忽略。
模板:
const int maxn=1e5+5; int par[maxn]; void init(int n){ for(int i=0;i<n;i++){ par[x]=i; } } int find(int x){ if(par[x]==x){ return x; }else{ return par[x]=find(par[x]); } } bool unite(int x,int y){ x=find(x); y=find(y); if(x==y)return false; else{ par[x]=y;//此处par[y]=x;也可以 return true; } } bool same(int x,int y){ return find(x)==find(y); }
其中unite函数也可以不返回布尔值,之所以在那里写了布尔值,是因为这样可以判断是否成功连接,在MST(最小生成树)的生成过程中使用较为方便。
例题:
1.连通
2.食物链
3.真假话
4.反向连通
5.MST
回来找时间再把例题的具体内容补上...
(未完待续)