1.普通并查集
用于记录节点之间的连接关系,使得相互连通关系的点可以用他们共同的父节点来表示。对于父节点不同的点可以通过父节点的合并来改成相互连通。主要用于判断图的连通性(如kruskal算法中)。
int find(int x)
{
if(x!=pre[x])//包括路径压缩
pre[x]=find(pre[x]);
return pre[x];
}
合并:
void join(int x,int y)
{
int a=find(x);
int b=find(y);
if(a!=b)
pre[a]=b;//只是简单的将节点合并
}
2.带权并查集
在一般并查集的基础上,在父节点的更改和合并时,同时记录下边的信息的改变。
int find(int x)
{
if(x!=pre[x])//包括路径压缩
{
int t=pre[x];//暂时记录下之前的父节点,便于更改路径压缩后的权值
pre[x]=find(pre[x]);
value[x]+=value[t];
}
return pre[x];
}
并:
void join(int x,int y)
{
int a=find(x);
int b=find(y);
if(a!=b)
{
pre[a]=b;
value[a]=-value[x]+value[y]+s;//并非每一个带权并查集都是这样更新
}//s为x与y之间的边权,因为a,b之间的权值不知道,因此这样表示
}
3.种类并查集
和带权并查集一样,再设定一个数组group[x],对其赋不同的值表示他和他的父亲的关系,具体看题目。和带权并查集不同的是,这里有一个取模的操作,一般有几个种类就mod几,把权值的累加变成累加结果mod p。
重点在于合并,利用向量加减的关系画图求出关系式