题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1213点击打开链接
题目描述:把互相认识的朋友划为一堆,赤裸的并查集教学题。
解题思路:
设立一个数组arr。先让arr【i】= i然后定义两种操作——也就是并查集的“并”和“查”。
= =。。果然还是先说一下我费尽心思弄出来的对并查集的基本理解。
i | 1 | 2 | 3 | 4 | 5 |
arr【i】 | 1 | 2 | 3 | 4 | 5 |
i | 1 | 2 | 3 | 4 | 5 |
arr 【i】 | 2 | 2 | 3 | 4 | 5 |
我们该考虑FIND操作到底怎么实现了,也就是输入这是第几个人,返回他所在的集合,return arr[ i ]也是可以的,但是我们应该找到他最原始的父亲,因为这样可以让我们把集合间的合并操作变得简单。假如现在我们知道 1 和 3 是盆友,3 和 2 不认识,怎么把 3 并入集合 2 呢?我们用FIND函数:int find(int x){return x == Father[x] ? x : Father[x] = find(Father[x]) ; } 来寻找 x 的最终父亲 FA,并把路径上所有的点都归入 FA。现在我们知道了 1 最终父亲是 2 ,好了,arr 【3】= 2 ,3就并入了集合 2。嘛~这么说感觉还是乱糟糟的,这道题的代码就是这两种操作的标准演示~详见代码
AC代码:
#include <cstdio>
#include <iostream>
using namespace std;
int arr[1050];
int find(int x)
{
return x==arr[x]?x:find(arr[x]);
}
void mer(int x,int y)
{
x=find(x);
y=find(y);
arr[x]=y;
}
int main()
{
int i,T,n,m,ans,a,b;
cin>>T;
while(T--)
{
ans=0;
cin>>n>>m;
for(i=1;i<=n;i++)
arr[i]=i;
while(m--)
{
cin>>a>>b;
mer(a,b);
}
for(i=1;i<=n;i++)
{
if(arr[i]==i)ans++;
}
cout<<ans<<endl;
}
return 0;
}
AC截图: