并查集0.3

来源:互联网 发布:jdk 7 windows i586 编辑:程序博客网 时间:2024/06/06 11:47

并查集

0.3


目录

  • 并查集
    • 基础并查集
      • 基本概念
        • 适用范围
        • 基础操作
          • 初始化
          • 查找
          • 合并
    • 带权并查集
      • 基本概念
      • 编程提示
        • 带权并查集的编写步骤
        • 关系的变形
    • 偏移并查集
      • 基本概念


基础并查集

基本概念

适用范围

  • 判断或标记图的连通性
  • 降低图的深度
  • 求父节点
  • 降低空间复杂度
  • 统计连通块个数

基础操作

初始化
for(int i=1;i<=n;i++){    f[i]=i;    c[i]=1;    rank[i]=0;}
查找
  • 注意两种查找方式返回值不同
int find(int i){    while(f[i]!=i) i=f[i];    /*路径压缩    会破坏树的结构*/    //递归,可以逐层更改 (循环无法实现回溯)    if(f[i]!=i) f[i]=find(f[i]);    return f[i];    ----------    //循环    int t=i;    while(f[t]!=t) t=f[t];    while(i!=t)    {        int t1=f[i];        f[i]=r;        i=t1;    }    return x;}
合并
void he(int x,int y){    //按秩合并    x=find(x);    y=find(y);    if(x==y)return;    if(rank[x]>rand[y])    {        f[y]=x;        c[x]+=c[y];    }    else    {        相反;        特判:if(rank[x]==rank[y])rank[y]++;    }

带权并查集

基本概念

带权并查集,又称关系并查集/种类并查集,是指通过某些特定的数组 (储存关系的容器) 来表示子节点与父节点的关系.为了使关系成立,需要保证树的深度小于等于2,所以在操作中需要用到路径压缩在压缩时,需要用一种方程来处理祖孙的关系,再将其反应到下一代 (即每次从根节点开始处理) ,显然用递归比较方便.同时,因为关系的单向性 (通常) ,不推荐使用按秩合并 (lca中因为dfs序,可以直接按秩合并) .

编程提示

带权并查集的编写步骤

  1. 确定此题为带权并查集(保证只有一个父节点)
  2. 找出各个点之间的对应关系
  3. 找出祖孙节点的方程(在find()函数内,路径压缩时)
  4. 找出合并时关系的改变方程 (究竟是直接操作根节点还是需要保留子节点的信息)
  5. 对于题目的询问作出回应

关系的变形

  • 对于题目中给出的非对立关系,可能需要设置相反的关系 (例:poj1182)
  • 即使直接连接两个子节点(非一家)方便,还是不能直接更新子节点,一定要先处理根节点
  • 关系一般可以枚举得出,通常要取模

偏移并查集

基本概念

关于偏移并查集,并没有找到适合的定义,所以这里的偏移并查集与上文所说的带权并查集不同 (即不是向量偏移) .这里的偏移是一种特殊的技巧,就是空间换时间.偏移并查集将关系全部存储起来,把推导出的关系放在k*i的空间里.好处是代码简单,不需要费心去找对应关系,只需要将关系扔进去,每次使用时调出来.在关系正误判断方面相当方便.

原创粉丝点击