#include <bits/stdc++.h>
using namespace std;
#define MAX_N 10000
long long par[MAX_N]; // 親
long long rankuf[MAX_N]; // 木の深さ
// n要素で初期化
void init(long long n) {
for (long long i = 0; i < n; i++) {
par[i] = i;
rankuf[i] = 0;
}
}
// 木の根を求める
long long find(long long x) {
if (par[x] == x) {
return x;
} else {
return par[x] = find(par[x]);
}
}
// xとyの属する集合を併合
void unite(long long x, long long y) {
x = find(x);
y = find(y);
if (x == y) return;
if (rankuf[x] < rankuf[y]) {
par[x] = y;
} else {
par[y] = x;
if (rankuf[x] == rankuf[y]) rankuf[x]++;
}
}
// xとyが同じ集合に属するか否か
bool same(long long x, long long y) {
return find(x) == find(y);
}
void solve(long long N, long long M, long long u[], long long v[]){
init(N);
for (int i = 0 ; i <= M-1 ; i++) {
unite(u[i], v[i]);
}
long long vcount[N-1+1];
long long ecount[N-1+1];
long long check[N-1+1];
memset(vcount, 0, sizeof(vcount));
memset(ecount, 0, sizeof(ecount));
memset(check, 0, sizeof(check));
for (int i = 0 ; i <= M-1 ; i++) {
if (check[u[i]] == 0) {
check[u[i]] = 1;
vcount[find(u[i])]++;
}
if (check[v[i]] == 0) {
check[v[i]] = 1;
vcount[find(v[i])]++;
}
ecount[find(u[i])]++;
}
long long res = 0;
for (int i = 0 ; i <= N-1 ; i++) {
if (ecount[i] + 1 == vcount[i]) res++;
if (vcount[i] == 0 && ecount[i] == 0 && find(i) == i) res++;
}
printf("%lld\n", res);
}
int main(){
long long M;
long long N;
scanf("%lld",&N);
scanf("%lld",&M);
long long u[M-1+1];
long long v[M-1+1];
for(int i = 0 ; i <= M-1 ; i++){
scanf("%lld",&u[i]);
scanf("%lld",&v[i]);
u[i]--;
v[i]--;
}
solve(N, M, u, v);
return 0;
}