并查集学习

HOJ1232来学习并查集

#include<iostream>
#include<vector>
using namespace std;
//封装好的并查集
class UF{//union find
    private:
        vector<int> v;//存储各个结点   v[i]=j  表示 第i个结点的代表元是j(所在树的根结点)
    public:
        //初始化
        UF(int n){//初始化  总共有n个结点  刚开始的时候v[i]=i
            for(int i=0;i<=n;i++){
                v.push_back(i);
            }
        }
        //根结点的查找
        int Find(int x){//查找x所在树的代表元(根结点)
            for(;;){
                if(v[x]!=x)
                    x=v[x];
                else
                    return x;
            }
        }
        //根结点的查找(递归)
        int Find2(int x){//递归的方法来找根结点
            if(v[x]==x) return x;
            else return Find2(v[x]);
        }
        //两棵树的合并
        bool Union(int x,int y){//把x和y合并
            x=Find(x);
            y=Find(y);
            if(x==y)
                return false;
            else{
                v[x]=y;
                return true;
            }
        }
};
int main(){
    int n,m,src,dest,root,count;
    while(cin>>n&&n!=0){
        UF uf(n);//n是城镇个数   m是当前公路个数
        cin>>m;

        //输入边  构造并查集,并查集的构造
        while(m--){
            cin>>src>>dest;//输入边的两个顶点
            if(uf.Find(src)!=uf.Find(dest)){//如果这两个点不能连通,
                uf.Union(src,dest);//把这个量结点所在的树  合并
            }
        }
        //逐个结点(城镇)检查是否连通,如果不连通就修一条路使她连通
        count=0;
        root=uf.Find(1);
        for(int i=2;i<=n;i++){
            if(UF.Find(i)!=root){
                uf.Union(i,1);
                count++;
            }
            cout<<count<<endl;
        }
    }
    return 0;
}
时间: 2024-08-02 19:38:46

并查集学习的相关文章

并查集--学习详解

[转] 文章作者:yx_th000 文章来源:Cherish_yimi (http://www.cnblogs.com/cherish_yimi/) 昨天和今天学习了并查集和trie树,并练习了三道入门题目,理解更为深刻,觉得有必要总结一下,这其中的内容定义之类的是取自网络,操作的说明解释及程序的注释部分为个人理解.并查集学习: l         并查集:(union-find sets) 一种简单的用途广泛的集合. 并查集是若干个不相交集合,能够实现较快的合并和判断元素所在集合的操作,应用很

并查集学习2

(转) 并查集由一个整数型的数组和两个函数构成.数组pre[]记录了每个点的前导点是什么,函数find是查找,join是合并. int pre[1000 ]; int find(int x)                                                                                                         //查找根节点 {      int r=x;     while ( pre[r ] != r )

并查集学习总结

并查集作用:判断两个元素是否在一个集合内. 方式:通过记录每个元素对应的par[x]值来判断,如果两者相等,则为同组,否则为不同组. _rank[maxn]的作用:_rank[i]记录的是每一个节点所在的树的高度,查询的时候意义不大,但是当两棵树合并的时候,当树的高度小的树连接到树的高度高的树会让树的整体高度较小,而保证查询优化. 状态压缩:并查集的状态压缩通过如下代码实现: int find(int x){ if(par[x]==x) return x; }else{ return par[x

续并查集学习笔记——Gang团伙题解

一言不合先贴题目 Description 在某城市里住着n个人,任何两个认识的人不是朋友就是敌人,而且满足: 1. 我朋友的朋友是我的朋友: 2. 我敌人的敌人是我的朋友: 所有是朋友的人组成一个团伙.告诉你关于这n个人的m条信息,即某两个人是朋友,或者某两个人是敌人,请你编写一个程序,计算出这个城市最多可能有多少个团伙? Input 第1行为n和m,N小于1000,M小于5000: 以下m行,每行为p x y,p的值为0或1,p为0时,表示x和y是朋友,p为1时,表示x和y是敌人. Outpu

并查集 (Union-Find Sets)及其应用

定义 并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题.常常在使用中以森林来表示. 集就是让每个元素构成一个单元素的集合,也就是按一定顺序将属于同一组的元素所在的集合合并. 主要操作 初始化 把每个点所在集合初始化为其自身. 通常来说,这个步骤在每次使用该数据结构时只需要执行一次,无论何种实现方式,时间复杂度均为O(N). 查找 查找元素所在的集合,即根节点. 合并 将两个元素所在的集合合并为一个集合. 通常来说,合并之前,应先判断两个元素是否属于

并查集入门(转)

并查集入门 并查集学习: l 并查集:(union-find sets) 一种简单的用途广泛的集合. 并查集是若干个不相交集合,能够实现较快的合并和判断元素所在集合的操作,应用很多,如其求无向图的连通分量个数等.最完美的应用当属:实现Kruskar算法求最小生成树. l 并查集的精髓(即它的三种操作,结合实现代码模板进行理解): 1.Make_Set(x) 把每一个元素初始化为一个集合 初始化后每一个元素的父亲节点是它本身,每一个元素的祖先节点也是它本身(也可以根据情况而变). 2.Find_S

【笔记】并查集

描述:并查集是一种对集合进行合并.查询等一系列操作.时间复杂度为O(a(n)) 比O(logn)还快. 代码: 1 int fa[sz];//集合数组 2 void init()//预处理 3 { 4 for(int i=1;i<=n;i++) 5 { 6 fa[i]=i;//初始时每个点都是一个独立的集合 7 rank[i]=0;//按秩合并 初始时每一个集合形成的树的高度为0: 8 } 9 } 10 int find(int x)//查询操作 返回x所在集合的代表元素 11 { 12 ret

算法学习——动态图连通性(线段树分治+按秩合并并查集)

在考场上遇到了这个的板子题,,,所以来学习了一下线段树分治 + 带撤销的并查集. 题目大意是这样的:有m个时刻,每个时刻有一个加边or撤销一条边的操作,保证操作合法,没有重边自环,每次操作后输出当前图下所有联通块大小的乘积. 首先观察到如果没有撤销操作,那么直接用并查集就可以维护,每次合并的时候乘上要合并的两个并查集大小的逆元,然后乘上合并之后的大小即可. 那么来考虑撤销,观察到如果并查集不带路径压缩,应该是可以处理撤销操作的. 但我们并不能直接做,因为并查集的撤销必须按顺序来,就相当于每次合并

【算法学习笔记】41.并查集 SJTU OJ 1283 Mixture

---恢复内容开始--- Description CC非常喜欢化学,并且特别喜欢把一大堆液体倒在一起. 现在CC有n种液体,其中m对会发生反应,现在她想把这n种液体按某种顺序倒入一个容器内,让她获得最刺激的体验,使危险系数尽量大. 我们可以这样计算危险系数,一开始容器内没有任何液体,危险系数为1.每次液体倒入容器时,若容器内已有一种或多种液体会与这种液体发生反应,则危险系数会乘2,否则危险系数不变. 请你求出把这n种液体倒在一起的最大危险系数. Input Format 第一行为两个数n和m.