动态连通性

并查集(union-find)算法

 

假设程序读入一个整数对p q,如果所有已知的所有整数对都不能说明p和q是相连的,那么将这一整数对写到输出中,如果已知的数据可以说明p和q是相连的,那么程序忽略p q继续读入下一整数对.

为了实现这个效果,我们设计并查集这种数据结构来保存程序已知的所有整数对的足够多的信息,并用它们来判断一对新对象是否连通,这个问题通俗地叫做动态连通性问题.

 

 

union-find算法的api

并查集(union-find)算法

 

为了方便,我们把每个对象称为触点,使用一个触点为索引的数组id[]作为基本的数据结构来表示所有分量,对于每个触点i,用find()方法来判定它分量所需的信息是否保存在id[i]中,connected()方法实现只用了一条语句 find(p) == find(q),它返回一个布尔值.

 

 

算法实现

public class  UF {
    
    private int[] id;    //分量id
    private int count;    //连通分量数目
    
    public UF(int N){
        id = new int[N];
        count = N;
        //初始化分量id数组
        for(int i = 0; i < N; i++){
            id[i] = i;
        }
    }
    
    //连通分量个数
    public int count(){
        return count;
    }
    
    //是否连通
    public boolean connected(int p, int q){
        return find(p) == find(q);
    }
    
    //在p q之间添加一条链接
    public void union(int p, int q){
        
    }
    
    //分量标识符
    public int find(int p){
    }
            
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int N = StdIn.readInt();
        UF uf = new UF(N);
        while(!StdIn.isEmpty()){
            int p = StdIn.readInt();
            int q = StdIn.readInt();
            if(uf.connected(p, q)){
                continue;
            }
            uf.union(p, q);
            StdOut.println(p + " " + q);
        }
        StdOut.println(uf.count()+"components");
    }

}
View Code

相关文章: