动态连通性问题

原创 2016年05月30日 13:37:00

动态连通性问题算法实现及优化

首先定义算法的API

方法 作用
UF(int N) 初始化触点及其他数据
int find(int p) 返回p所在连通分量的标识符
int union(int p,int q) 在p和q之间添加一条线
int count () 返回连通分量的数量
boolean connected(int p,int q) 如果p和q之间有一条线就返回true

1.好了,API已经定义好了,下面可以实现这个API,下面是第一个版本。实现思想是利用判断id[q]和id[p]是否相等来判断它们是否在同一个连通分量中。它的缺点是一般无法处理大规模问题,因为每次调用它都需要扫描一次数组,对于最终值得到少量连通分量的问题运行时间是平方级别的。

public class UnionFind {
    private int count;//记录连通分支数
    private int[] id;
    public UnionFind(int N){
        count = N;
        id = new int[N];
        for(int i = 0;i<N;i++)//完成将id初始化0~N-1
            id[i] = i;
    }
    public int find(int p){
        return id[p];
    }
    public int getCount(){
        return count;
    }
    public boolean connected(int p,int q){
        return id[p] == id[q];
    }
    public void union(int p, int q){//缺点:一般无法处理大规模问题,因为每次调用它都需要扫描一次数组,对于最终值得到少量连通分量的问题运行时间是平方级别的
        int pID = id[p];
        int qID = id[q];
        if(pID == qID) //思路:利用判断id[q]和id[p]是否相等来判断它们是否在同一个连通分量中
            return;//如果相等就什么也不做,因为它们本来就在一个连通分支里面
        for(int i = 0;i<id.length;i++){
            if(id[i] == pID)
                id[i] = qID;//将p所在的连通支路全部改为q,合并两个连通分支
        }
        count--;//合并之后因为连通分支数少一,所以减一
    }
}

2.上面的那个算法不适用与大数据处理,原因是对于最终得到的连通分量问题的运行时间是平方级别的。下面的这个算法它优化了union()方法,并修改了find()方法以配合union()方法的使用。它的设计思想是定义与之前不同的数据结构,每个触点所对应的id[]元素都是同一个分量中的另一个触点的名称(也有可能是它自己)——我们将这种联系称为链接。每个连通分量都有一个根触点。根触点的特点是id[i] = i。这种数据结构使得union()在最坏情况下得到的结果是平方级别的,一般情况下是线性对数级别的。而find()方法的运行时间取决于数的高度。

public class QuickUnion {
    private int count;//记录连通分支数
    private int[] id;
    public QuickUnion(int N){
        count = N;
        id = new int[N];
        for(int i = 0;i<N;i++)//完成将id初始化0~N-1
            id[i] = i;
    }
    public int find(int p){
        while(p != id[p])
            p = id[p];
        return p;//返回连通标号
    }
    public int getCount(){
        return count;
    }
    public boolean connected(int p,int q){
        return find(p) == find(q);
    }
    public void union(int p, int q){//最坏情况下得到的连通分量运行时间是平方级别的
        int pRoot = find(p);
        int qRoot = find(q);
        if(pRoot == qRoot)
            return;
        id[pRoot] = qRoot;
        count--;
    }
}

3.下面是第三种方法实现,它进一步优化了第二种实现,使得在最坏情况下union()也保持线性对数级别的运行时间。设计思想是在union()中不是随意将一棵树链接到另一棵树中,而是通过添加一个数组来记录每颗数的大小,将较小的一颗链接到较大的一颗树上。我们将它称为加权quick-union算法。

public class WeightedQuickUnion {
    private int[] id;//父链接数组,由触点作为缩引
    private int[] sz;//存储各个触点具有的数据个数
    private int count;
    public WeightedQuickUnion(int N){
        count = N;
        id = new int[N];
        sz = new int[N];
        for(int i = 0;i<N;i++){
            id[i] = i;
            sz[i] =1;
        }
    }
    public int getCount(){
        return count;
    }
    public boolean connected(int p,int q){
        return find(p) == find(q);
    }
    private int find(int p){
        while(p != id[p])
            p = id[p];
        return p;
    }
    public void union(int p,int q){
        int i = find(p);
        int j = find(q);
        if(i == j)
            return;
        if(sz[i] < sz[j]){//将较小的连通分量链接到较大的连通分量中
            id[i] = j;
            sz[j] += sz[i];
        }
        else{
            id[j] = i;
            sz[i] += sz[j];
        }
        count --;
    }
}

总结:由上面的算法优化可以知道,算法优化不是一步到位的,它中间需要一个过程

版权声明:本文为博主原创文章,未经博主允许不得转载。

算法分析学习笔记(一) - 动态连通性问题的并查集算法(上)

一. 写在前面的话      “算法分析学习笔记”系列是我在Coursera上选修Sedgewick教授的“Algorithms”公开课过程中积累的一些学习心得。本篇是该系列的第一篇,主题是动态连通...

bzoj3514:Codechef MARCH14 GERALD07加强版 关于一类LCT维护动态图的连通性问题

3514: Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec  Memory Limit: 256 MB Submit: 1900  Solved: ...

动态连通性问题(2)

问题描述: 问题是输入一列整数对,,其中每个整数都表示一个某种类型的对象,一对整数p,q被理解为相连的,我们假设相连是一种等价关系,即具备自反,堆成,传递三种特性。 当从程序中读取整数对时,如果已...
  • pusude
  • pusude
  • 2016年09月02日 23:22
  • 241

算法分析学习笔记(一) - 动态连通性问题的并查集算法(下)

三. 实际应用——解决物理化学中的渗滤模型问题      该问题来自于http://coursera.cs.princeton.edu/algs4/assignments/percolation.h...

图的连通性问题

  • 2017年04月12日 09:56
  • 1.79MB
  • 下载

动态连通性:union-find算法(常规搜索、树状触点搜索、加权树搜索的算法分析)

算法 提出动态连通性问题:输入一列整数对,其中每个整数都表示一个某种类型的对象,一对整数对p和q可以被理解为p和q是相连的。 他们具有 自反性:p和p相连; 对称性:p和q相连,q和p相连; ...

基于连通性状态压缩的动态规划--【插头DP】模板超级详细解释

断断续续卡了本公举三天的插头dp终于搞完了,貌似好多网友也都是学了好多天才搞懂的,特别用成就感,作为一个模板160+行的dp也是醉了 首先一定要看陈丹琪的论文!一个高中女孩能让许多大老爷们为...

算法-动态连通性

概念简单点理解就是连接两点,如果已经是连通的则忽略,比如下图:应用 网络连通性: 判断大型计算机网络中,两台计算机是否需要新连接才能通信 变量名等价性: 能判断两变量名是否等价 数学集合: 两个...

动态连通性、并查集(union-find)算法介绍

本文主要介绍解决动态连通性一类问题的一种算法,使用到了一种叫做并查集的数据结构,称为Union-Find。更多的信息可以参考Algorithms 一书的Section 1.5,实际上本文也就是基于它的...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:动态连通性问题
举报原因:
原因补充:

(最多只允许输入30个字)