#include <iostream>
using namespace std;
int f[1001];
int n,m;
int getf(int x)
{
int r = x;
while(r != f[r])
while(f[i]!= r)///压缩路径:使得自己从下往上走,直到到达根节点,并且使得找过的点都变成最后的大boss
{
j = f[i];///并且使得自己变成自己的父节点,直到到达根节点
f[i] = r;
i = j;
}
/*int getf(int v)///用递归实现找大boss
{
if(f[v] == v)
return v;
else
{
f[v] = getf(f[v]);///压缩路径
return f[v];
}
}*/
void mix(int a,int b)///合并过程
{
int t1,t2;
t1 = getf(a);
t2 = getf(b);
if(t1 != t2)
{
f[t2] = t1;///初始化,使得每个强盗的大boss都是自己本身
}
return;
}
int main()
{
cin >> n >> m;
int x,y;
int sum = 0;
for(int i = 1;i <= n;i++)
{
f[i] = i;
}
for(int i = 1;i <= m; i++)
{
cin >> x >> y;
mix(x,y);
}
for(int i = 1;i <= n;i++)
if(f[i] == i) sum ++;
cout << sum << endl;
return 0;
}
using namespace std;
int f[1001];
int n,m;
int getf(int x)
{
int r = x;
while(r != f[r])
r = f[r];///找到大boss
while(f[i]!= r)///压缩路径:使得自己从下往上走,直到到达根节点,并且使得找过的点都变成最后的大boss
{
j = f[i];///并且使得自己变成自己的父节点,直到到达根节点
f[i] = r;
i = j;
}
}
/*int getf(int v)///用递归实现找大boss
{
if(f[v] == v)
return v;
else
{
f[v] = getf(f[v]);///压缩路径
return f[v];
}
}*/
void mix(int a,int b)///合并过程
{
int t1,t2;
t1 = getf(a);
t2 = getf(b);
if(t1 != t2)
{
f[t2] = t1;///初始化,使得每个强盗的大boss都是自己本身
}
return;
}
int main()
{
cin >> n >> m;
int x,y;
int sum = 0;
for(int i = 1;i <= n;i++)
{
f[i] = i;
}
for(int i = 1;i <= m; i++)
{
cin >> x >> y;
mix(x,y);
}
for(int i = 1;i <= n;i++)
if(f[i] == i) sum ++;
cout << sum << endl;
return 0;
}