#include<cstdio>
using namespace std;
const int MAXN = 1000;
int father[MAXN]; //定义父节点数组
int height[MAXN]; //结点高度数组
void Initial(int n) {
for(int i = 0; i <= n; ++i) {
father[i] = i; //每个结点的父节点是自己
height[i] = 0; //高度都是0
}
}
int Find(int x) { //查找根节点
if (x != father[x]) { //路径压缩
father[x] = Find(father[x]);
}
return father[x];
}
void Union(int x, int y) {
x = Find(x);
y = Find(y);
if(x != y) { //矮树作为高数的子树。使拼接后不增加高度
if(height[x] > height[y]) {
father[y] = x;
} else if (height[y] > height[x]) {
father[x] = y;
} else {
father[y] = x;
height[x]++;
}
}
return;
}
int main() {
int n, m;
while(scanf("%d", &n) != EOF) { //输入城镇树
if(n == 0) {
break;
}
scanf("%d", &m); //输入街道数
Initial(n); //初始化
while(m--) {
int x, y;
scanf("%d", &x);
scanf("%d", &y);
Union(x, y); //合并集合
}
int answer = -1;
for(int i = 1; i <= n; ++i) {
if(Find(i) == i) {
answer++;
}
}
printf("%d\n", answer);
}
return 0;
}