1、知识点:连通分量
2、思路:并查集
/*用途:
**说明:
**算法:并查集
*/
//#define LOCAL
#include <cstdio>
#include <string.h>
using namespace std;
#define MAXN 1000+10
int N, M;
int pre[MAXN];
int block[MAXN];
int find(int x);
void uni(int x, int y);
int main()
{
#ifdef LOCAL
freopen(".in", "r", stdin);
freopen(".out", "w", stdout);
#endif
while(scanf("%d", &N) && N){
scanf("%d", &M);
for(int i=1; i<=N; i++)
pre[i] = i;
for(int i=1; i<=M; i++){
int a, b;
scanf("%d%d", &a, &b);
uni(a, b);
}
memset(block, 0, sizeof(block));
for(int i=1; i<=N; i++)
block[find(i)] = 1;
int ans = 0;
for(int i=1; i<=N; i++)
if(block[i])
ans++;
printf("%d\n", ans-1);
}
return 0;
}
inline int find(int x)
{
int top = x;
while(top != pre[top])
top = pre[top];
int temp; //暂时保存x以前的上级结点
while(pre[x] != top){ //路径压缩
temp = pre[x];
pre[x] = top;
x = temp;
}
return top;
}
inline void uni(int x, int y)
{
int fx, fy;
fx = find(x);
fy = find(y);
if(fx != fy)
pre[fx] = fy;
}