并查集:并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。
举个例子
首先在地图上给你若干个城镇,这些城镇都可以看作点,然后告诉你哪些对城镇之间是有道路直接相连的。最后要解决的是整幅图的连通性问题。比如随意给你两个点,让你判断它们是否连通,或者问你整幅图一共有几个连通分支,也就是被分成了几个互相独立的块。
以下面这组数据输入数据来说明
4 2 1 3 4 3
第一行告诉你,一共有4个点,2条路。下面两行告诉你,1、3之间有条路,4、3之间有条路。那么整幅图就被分成了1-3-4和2两部分。城镇有几百个,路有不知道多少条,而且可能有回路。 这可如何是好?
#include <iostream>
using namespace std;
const int N = 100;
int f[N];//f[i] = j.表示:i的祖先是 j.
int main()
{
void init();//初始化,先使每个节点的祖先都是自己,各自为政。
int getFather( int i );//获取 i 号节点的祖先
//如果a,b祖先相同,则不操作。否则,依照靠左的原则,将b的祖先归顺与a的祖先,即b的祖先的祖先是a的祖先,使a,b拥有相同的祖先.
void merge( int a, int b );
int n,m;//节点数,关系数
init();
cin>>n>>m;
cout << "input relations:\n";
for( int i=0; i<m; ++i ){
int a,b;
cin>>a>>b;//表示a,b有相同祖先
merge(a,b);
}
int sum=0;
for( int i=1; i<=n; ++i ){
if( f[i]==i )
++sum;
}
cout << "The number of groups is "<<sum<<endl;
return 0;
}
void init(){
for( int i=0; i<N; ++i )
f[i] = i;
}
//获取祖先
int getFather( int i ){
if( f[i]==i )
return i;
else{
f[i] = getFather(f[i]);//实现了路径压缩
return f[i];
}
}
//合并
void merge( int a, int b ){
int a_father = getFather( a );
int b_father = getFather( b );
if( a_father!=b_father ){
f[b_father] = a_father;
}
}