并查集
并查集是数据结构中的一个重要算法,可以管理元素分组,并查集由三部分构成:初始化,找父节点,合并结点,直接来看并查集的模板:
void init(int n)
{
for(int i=1;i<=n;++i)
fa[i]=i,ran[i]=0;
//刚开始每个人都是自己的老大,每个人都没有手下
}
int ffind(int x)
{
return x==fa[x]?x:fa[x]=ffind(fa[x]);
}
void unite(int x,int y)
{
int fx=ffind(x);
int fy=ffind(y);
if(fx==fy) return;
if(ran[fx]<ran[fy])
fa[fx]=fy;
else
{
fa[fy]=fx;
if(ran[fx]==ran[fy])
ran[fx]++;
}
}
下面是一道并查集的裸题:http://poj.org/problem?id=1611,题意为:0是嫌疑犯,和0是朋友的全都是嫌疑犯,找出嫌疑犯的个数,下面为并查集运用的题解:
#include<iostream>
#include<stdio.h>
#include<cstring>
using namespace std;
const int N=30005;
int fa[N],s[N],h[N];
int ffind(int x)
{
return x==fa[x]?x:fa[x]=ffind(fa[x]);
}
inline void unite(int x,int y)
{
int fx=ffind(x);
int fy=ffind(y);
if(fx==fy) return;
if(h[fx]<h[fy])
fa[fx]=fy;
else
{
fa[fy]=fx;
if(h[fx]==h[fy])
h[fx]++;
}
}
int main()
{
int n,m,data;
while(scanf("%d%d",&n,&m)&&(n||m))
{
int ans=1;
for(int i=0; i<n; i++)
fa[i]=i,h[i]=0;
for(int i=1; i<=m; i++)
{
int k;
scanf("%d%d",&k,&data);
for(int j=2; j<=k; j++)
{
scanf("%d",&s[j]);
unite(data,s[j]);
}
}
for(int i=1; i<n; i++)
if(ffind(fa[i])==fa[0])
ans++;
printf("%d
",ans);
}
}