再学一次并查集,感觉原来学过的太水了, = = 、 自从CCPC国赛被打回原形以后……
废话不多说,重新系统地学习一下这个数据结构
并查集:本质是一颗树,也就是一种数据结构,主要为了解决的问题就是是不是一个集合的问题,尤其是一些具有传递性质的问题;
三个功能
初始化:把所有结点的father都指向它自身
合 并:把应该在一个集合的点连接到一起
查 找:查找某个点的父节点,看看是否是一个集合
#include<stdio.h>
#include<iostream>
using namespace std;
int father[1005];
void init(int n)//初始化集合
{
for(int i = 1 ; i <= n ; i ++)
{
father[i] = i;
}
}
int find(int x)//查找根结点,并且进行路径压缩
{
int i = x;
while(father[i] != i)
{
i = father[i];
}
int k = x;
int j;
while(father[k]!=i)//查找到根结点之后把每个结点的父节点都更新为根节点
{
j = father[k];
father[k] = i;
k = j;
}
return i;
}
void merge(int x,int y)//合并两个集合
{
int fx = find(x);
int fy = find(y);
if(fx!=fy)
father[fx] = fy;
}
int main()
{
int n,m;
int x,y;
while(scanf("%d",&n)&&n)
{
init(n);
scanf("%d",&m);
for(int i = 1 ; i <= m; i ++)
{
scanf("%d %d",&x,&y);
merge(x,y);
}
int ans = 0;
for(int i = 1 ; i <= n; i++)
{
if(father[i]==i)
ans++;
}
cout<<ans-1<<endl;
}
return 0;
}