#include<stdio.h>
#define infile "felinare.in"
#define outfile "felinare.out"
#define nmax (2*(9*1000+1))
#define mmax (2*nmax+20*1000+1)
#define inf ~(1<<31)
struct lista
{
int n,p,f; //nodul, pozitia si fluxul de pe acest arc
} l[mmax], lt[mmax]; //lista normala si lista transpusa
int p[nmax], pt[nmax]; //pozitia din cele liste a nodurilor
int viz[nmax]; //vector de vizita
int st,fi; //nodul de start si nodul final pt reteaua de transport
int n,m; //numarul de noduri respectiv muchii
int flux; //aici vom calcula fluxul maxim
//adaugam arcul (x,y) in lista
inline void add(struct lista l[mmax], int p[nmax], int m, int x, int y)
{
l[m].n=y; l[m].p=p[x]; p[x]=m;
}
//modifica in lista de adiacenta a unui nod, fluxul
inline void modifica(struct lista l[mmax], int p[nmax], int x, int y, int f)
{
int ul=p[x]; //pozitia din lista a lu fisu
while(ul)
{
if(l[ul].n==y) { l[ul].f=f; break; } //am gasit arcul....ii modificam fluxul si oprim
ul=l[ul].p; //fiusu
}
}
void citire()
{
int i,x,y;
scanf("%d %d\n",&n,&m); //numarul de linii si muchii
for(i=1;i<=m;i++)
{
scanf("%d %d\n",&x,&y);
y+=n; //fiind nevoiti ca dupa sa facem cuplaj maxim....nodurile din partea cealalta vor incepe numararea de la n+1
add(l,p,i,x,y); //adaug arcul pt graful normal
add(lt,pt,i,y,x); //adaug arcul pt graful transpus
}
}
//transformam graful in retea de transport...(avem nevoie sa facem dupa cuplaj maxim in graf bipartit)
void initializare()
{
int i;
st=n+1; fi=st+1; //nodul de intrare si cel de iesire....
for(i=1;i<=n;i++) //adaugam legatura de la nodul st la toate nodurile din prima grupa
{
++m; //facem loc in lista :P
add(l,p,m,st,i); //adaugam in graful normal
add(lt,pt,m,i,st); //adaugam si in graful transpus
}
for(i=1;i<=n;i++) //adaugam legatura de la toate nodurile din grupa a 2-a la nodul final...
{
++m; //facem loc in lista
add(l,p,m,i+n,fi); //graful normal
add(lt,pt,m,fi,i+n); //graful transpus
}
}
//facem parcurgere in adancime...pt a afla fluxul maxim in graf :P...bipartit
int dfs(int x, int f) //nodul in care ne aflam...si fluxul care il putem folosi
{
viz[x]=1; //il marcam ca vizitat
if(x==fi) { flux+=f; return 0; } //am ajuns la nodul final...salvam fluxul...si returnam 0 (l-am folosit pe tot)
int ul,c;
for(ul=p[x];ul&&f;ul=l[ul].p) //trecem pe la fiecare copil al lui x
if(!viz[l[ul].n]&&!l[ul].f) //daca nu a fost vizitat, si daca nu avem arcul saturat
{
c=dfs(l[ul].n,1); viz[l[ul].n]=0; //nodul e clar ca il putem apela doar cu flux 1
if(!c) //daca nodul nu a returnat cost....l-a folosit :P
{
l[ul].f=1; //saturam arcul
modifica(lt,pt,l[ul].n,x,1); //modificam fluxul si in lista transpusa
f-=1; //scadem k am folosit din flux
}
}
for(ul=pt[x];ul&&f;ul=lt[ul].p) //trecem pe la feicare copil al lui x in graful transpus
if(!viz[lt[ul].n]&<[ul].f) //daca nodul nu a mai fost vizitat....si daca am flux (pt k parcurg arcul in sens invers)
{
c=dfs(lt[ul].n,1); viz[lt[ul].n]=0; //parcurgem nodul cu flux 1
if(!c) //daca a fost folosit fluxul de pe acest nod
{
lt[ul].f=0; //scadem fluxul folosit
modifica(l,p,lt[ul].n,x,0); //modificam fluxul si in lista normala a retelei
f-=1; //am folosit fluxul :P
}
}
return f; //returnam fluxul ramas :P
}
int main()
{
freopen(infile,"r",stdin);
freopen(outfile,"w",stdout);
citire(); //citire
initializare(); //transformam graful in retea de transport :P
dfs(st,inf);
printf("%d\n",(2*n)-flux);
fclose(stdin);
fclose(stdout);
return 0;
}