并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。常常在使用中以森林来表示。
集就是让每个元素构成一个单元素的集合,也就是按一定顺序将属于同一组的元素所在的集合合并。
并查集里的每一个组表示组内所有元素代表的情况都同时发生或不发生。
为了更好的理解什么是并查集,我要供出这篇神文了江湖上的并查集嘻嘻
简言之,
查询问题find函数就是找帮主,而join函数是我让两个人做好朋友≧▽≦,所以必须让帮主也成为好朋友,两个帮派就形成了一个门派。
因为一层层的找帮主很慢,所以要进行路径压缩,争取就两级,上级就是帮主,优化了算法^__^
例题 SDNU1217CD收藏
Description
lmh平常爱听歌,所以买了很多的CD来收藏,但是因为平常整理不当,所以忘记了这些CD的歌手是谁。现在他想知道他到底收藏了多少位歌手的专辑,于是他想了一个办法,同时拿出两个CD来听,可以分辨出来是否为同一个歌手唱的。(如果没有说明则认为是没有分辨出来,为不同歌手)现在他列了一个表记录哪些专辑是同一歌手,但他面对着这一堆记录不知如何处理,请你告诉他到底他有多少个歌手的专辑。
Input
第一行n,m。n表示CD的个数(标号分别为1到n),m表示lmh所分辨出来的共有几组。接下来的m行每一行有两个数a,b。表示a唱片和b唱片是同一个歌手。(1<=n,m<=10000)
Output
总计的歌手数量。
Sample Input
10 9
1 2
3 4
5 2
4 6
2 6
8 7
9 7
1 6
2 4
Sample Output
3
想法:专辑和歌手,输出这么多专辑一共有几个歌手的,一个歌手可以出好几张专辑啊,比如我宇(骄傲脸)。数据比较水,甚至单纯用递归都能做出来,但重在理解并查集啊O(∩_∩)O
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
int f[10005];//记录的是每个专辑的歌手
int find(int v)
{
if(f[v]==v)
return v;
else
f[v]=find(f[v]);
return f[v];
}
int join(int u,int v)
{
int t1,t2;
t1=f[u];
t2=f[v];
if(t1!=t2)
f[t2]=t1;//我把变量写成了u和v,要注意这好多变量○| ̄|_
return 0;
}
int main()
{
int sum=0,i;
int n,m,a,b;
while(~scanf("%d %d",&n,&m))
{
//memset(f,0,sizeof(f));不知道问什么这里不用清空也过了QAQ
for(i=1;i<=n;i++)
{
f[i]=i;
}
for(i=1;i<=n;i++)
{
cin>>a>>b;
join(a,b);
}
for(int i=1;i<=n;i++)
{
if(f[i]==i)
sum++;
}
cout<<sum<<endl;
}
return 0;
}
ps:这篇博客有毒,我交了四遍才交上:)