import java.util.*;
public class Main
{
public static void main(String [] args)
{
Scanner scn = new Scanner(System.in);
int n = scn.nextInt();
int m = scn.nextInt();
//directed graph
HashMap <Integer, HashSet<Integer>> graph = new HashMap <> ();
for(int i = 1; i<=m; i++)
{
int x = scn.nextInt();
int y = scn.nextInt();
if(!graph.containsKey(x))
graph.put(x, new HashSet <Integer> ());
if(!graph.containsKey(y))
graph.put(y, new HashSet <Integer> ());
//directed graph
//directed from smaller value
//node to larger valued node
if(x <= y)
{
graph.get(x).add(y);
}
else
{
graph.get(y).add(x);
}
}
System.out.println(beautifulVertices(graph));
}
public static long beautifulVertices(HashMap <Integer, HashSet<Integer>>graph)
{
HashMap <Integer, Boolean> visited = new HashMap <> ();
long finalAns = 0; int ans = 0;
for(int i : graph.keySet())
{
if(visited.containsKey(i))
continue;
//apply bfs
Queue <Integer> q = new LinkedList <> ();
//adding the parent vertex of the component
q.add(i);
ans = 0;
while(!q.isEmpty())
{
int rv = q.remove();
if(visited.containsKey(rv))
continue;
visited.put(rv,true);
//no. of children for
//rv, if rv is considered
//the current parent then,
//removed vertex children
int rvc = graph.get(rv).size();
for(int nbr : graph.get(rv))
{
if(visited.containsKey(nbr))
continue;
//no. of children for current vertex
//current vertex children
int cvc = graph.get(nbr).size();
if(cvc > rvc)
ans++;
q.add(nbr);
}
}
finalAns += ans;
}
return finalAns;
}
}