算法总结——并查集

搞了两年ACM,终于准备写一些博客了,总得留下点什么。

不了解并查集的话,推荐这个博客学习,讲的很有意思,当时笑出声。

下面写一下自己的理解吧

并查集最简单的用法,就是把不同的元素归并到一个集合里。
在集合里选出一个老大作为代表,集合里的其他元素都是他的小弟。这样,就可以判断任意两个元素是不是属于同一个集合,还可以计算一个图中有多少个连通块。
并查集支持删点操作
但并不是所有模型都能删点哦!如果点与点之间的关系是在同一集合或者不在同一集合这种关系,就可以删点。比如:A-B&&B-C,删掉点B,A和C还在同一集合。但是,如果点与点的关系是连通与不连通的关系,就不能删点了。比如 A-B&&B-C,删掉点B,A和C就不连通了。**总结就是,如果删完点后会影响其他点之间的关系,这样就不能删点**
那么如何删点呢
网上的叫法是建立“虚点”,意思就是用一个数组把元素指向一个值,用这个值来代替元素。如:
find(id[a]);//用id[a]来代替a。`
删除一个点的操作就是,把元素指向一个新的值,以前的值就丢弃了。
void delete(a){
        id[a] = overloop++;//overloop大于n
}
怎么删除不能删的点和边呢
一般做法都是逆向处理询问,离线处理,删边换成加边,删点换成加点。
并查集的难点就是处理点与点之间的关系
像线段树一样,并查集与能在点上存放&处理数据。**并查集处理的是点与点之间的关系**

比如:*BZOJ 1015*
这题要求的是x所在的集合内是否存在value值大于value[x]的点。
在连通两个点的时候,选择value值较大的点为根即可。
void join(int x,int y){
        int fx = Find(x);
        int fy = Find(y);//找到双方的老大
        if(fx!=fy){
            if(value[fx]>value[fy])father[fy] = fx;
            else father[fx] = fy   //谁的老大更厉害就选谁。
        }
    }
*POJ 1984*
这里要求一个图中任意两个点的manhattan距离(这里简化一下问题,把manhattan距离改为平面距离,二维降到一维)。
要怎么求呢?
易知,任意两个点之间肯定有一个老大(根结点),那么记录每个点与根结点的距离,就可以求得两个点间的距离了。
但是,老大是会变的!要更新信息。
int Find(int x){
        if(x!=father[x]){
            int fa = Find(father[x]);
            distance[x]+=distance[father[x]];//x点到根结点的距离就是x到x的父亲的距离加上x的父亲到根结点的距离。
            father[x] = fa;
        }
        return father[x];
}
void join(int x,int y){
    int fx = Find(x);
    int fy = Find(y);
    if(fx!=fy){
        father[fy] = fx;
        distance[fy] = distance[x]-distance[y] + len;//len是x与y的距离
    }
}

感觉写的很差哈,写博客好费时间啊
还没写完,下次更新吧,争取用图来解释问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值