1 等价关系和等价类
等价关系
如果集合S中的关系R是自反的,对称的,传递的,则称他为一个等价关系。
——自反:x=x;
——对称:若x=y,则y=x;
——传递:若x=y、y=z,则x=z。要求:x、y、z必须要同一个子集中。
等价类
如果R是集合S的等价关系。对于任何x∈S,由[x]R={y|y∈S and xRy}给出的集合[x]RS 称为由x∈S生成的一个R的等价类。
2并查集基本操作
划分等价类
</pre><span style="font-size:12px;"></span><pre class="sh-cpp sh-sourceCode" style="font-family:Courier New,Courier,monospace"><span class="sh-symbol"></span><pre class="sh-cpp sh-sourceCode" style="font-family:Courier New,Courier,monospace"><span class="sh-keyword">for</span><span class="sh-symbol">(</span><span class="sh-type">int</span> i <span class="sh-symbol">=</span> <span class="sh-number">0</span> <span class="sh-symbol">;</span> i <span class="sh-symbol"><</span> maxn <span class="sh-symbol">;</span> i <span class="sh-symbol">++)</span>
fa<span class="sh-symbol">[</span>i<span class="sh-symbol">]</span> <span class="sh-symbol">=</span> i <span class="sh-symbol">;</span>
查找
int Find(int x)
{
if(x == fa[x]) return x ;
else return fa[x] = Find(fa[x]) ; //路径压缩
}
合并
void Union(int x ,int y)
{
int fx = Find(id[x]) ;
int fy = Find(id[y]) ;
if(fx != fy)
fa[fx] = fy ;
}
删除
并不是真正地删除某节点。因为并查集是树形结构,所以无法简单的把一个节点从一棵树中删去并维护原来的信息。那这里用到的思想就是还是保持原来的树的结构不变,只是把被删掉的那个点设为虚点,并新建一个点,把原来的点映射到这个新点上,代表以后的操作都是对这个新点进行操作。这样空间开销虽然大,但还是可以解决问题的。
int fa[maxn] , id[maxn] ;
int cnt = n ; for(int i = 0 ; i < maxn ; i ++) fa[i] = i ; for(int i = 0 ; i < n ; i ++) id[i] = i ; void delete(int x) { id[x] = cnt ++ ; }
3 并查集应用
(1)并和查有关的集合操作
并查集可以用于相关的集合操作,如判定一个无向图是否有环,输出一个无向图的连通分量个数,kruscal最小生成树的操作。一些基于集合,有添加其它性质的集合操作。
题目:TOJ2469 Friends 、TOJ3294 Building Blcok 、TOJ3732 Dragon Balls
(2)种类相关并查集操作
题目中出现的元素分为一些种类,描述中会给出相关的描述信息,判断描述的正确性,即是否有悖于之前对这些元素种类的描述。一般可以增加一个kind属性来表示元素的种类。
题目 :POJ1182 食物链、TOJ1706 A Bug’s life、POJ1733 Parity Game、TOJ3413 How Many Answers Are Wrong、
(3)用于优化
并查集更多地应用于 dp 或者贪心中的优化,用来降低复杂度。 题目:TOJ1681 Supermarket
(4)反向进行并查集操作
与并查集不同,给出一个图中原有的一些边,然后给出操作,操作不是向图中添加边,而是在已有的边上,将边删除。对于该种情况,需要把首先读入所有操作,把要求删除的边全部删除,再按照从后往前的顺序处理操作,这样删边操作又重新转化为了添边的操作。
题目:ZOJ3261 Connections in Galaxy War
参考博客: 点击打开链接