并查集由一个整数型的数组和两个函数构成。数组pre[]记录了每个点的前导点是什么,函数find是查找,join是合并。
用法
并查集是由一个数组pre[]
,和两个函数构成的,一个函数为find()
函数,用于寻找前导点的,第二个函数是join()
用于合并路线的
int find(int x)
{
int r=x,i=x,j;
while(pre[r]!=r)
r=pre[r];//找到他的前导结点
while(i!=r)//路径压缩算法
{
j=pre[i];//记录x的前导结点
pre[i]=r;//将i的前导结点设置为r根节点
i=j;
}
return r;
}
路径压缩为了加快查找的速度,将x点与其根节点直接相连,构造成类似于只有叶子结点而没有分支结点的树
join()函数
void join(int x,int y)
{
int a=find(x);//x的根节点为a
int b=find(y);//y的根节点为b
if(a!=b)//如果a,b不是相同的根节点,则说明ab不是连通的
{
pre[a]=b;//我们将ab相连 将a的前导结点设置为b
}
}
初始化
我们将每一个结点的前导结点设置为自己,如果在join函数时未能形成连通,将独立成点
for(int i=0;i<n;i++)//n表示输入的结点的个数
{
pre[i]=i;//将每一个结点的前导点设置为自己
}
来看一个实例
以下面这组数据输入数据来说明
第一行告诉你,一共有4个点,2条路。下面两行告诉你,1、3之间有条路,4、3之间有条路。那么整幅图就被分成了1-3-4和2两部分。只要再加一条路,把2和其他任意一个点连起来,畅通工程就实现了,那么这个这组数据的输出结果就是1。好了,现在编程实现这个功能吧,城镇有几百个,路有不知道多少条,而且可能有回路。 这可如何是好?
#include <stdio.h>
int pre[1000 ];
{
while (pre[r ]!=r)
int i=x; int j;
{
pre[i ]=r;
}
}
{
while(scanf("%d",&n) && n) //读入n,如果n为0,结束
total=n-1;
for(i=1;i<=n;i++)
pre[i ]=i; //共有m条路
{ //下面这段代码,其实就是join函数,只是稍作改动以适应题目要求
scanf("%d %d",&p1,&p2);
f2=find(p2);
//分支的总数就减少了1,还需建的路也就减了1
{
total--;
//如果两点已经连通了,那么这条路只是在图上增加了一个环 //对连通性没有任何影响,无视掉
//最后输出还要修的路条数
}
}