using namespace std;
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <iostream>
#include <cmath>
#include <cassert>
#include <deque>
#define NDEBUG
#define FIN "felinare.in"
#define FOUT "felinare.out"
#define maxn 8192
#ifndef NDEBUG
int stp;
#endif
vector<vector<int> > x;
vector<vector<bool> > a;
//char aa[maxn+2000][(maxn/8) +2000];
struct nod { int x, y;nod(){}; nod(int a, int b){x=a; y=b;};};
int n, m, E;
int source, sink;
int t[maxn<<1];
int d[maxn<<1];
bool Viz[maxn<<1];
int bfs();
void solve();
void read()
{
int i,p, q;
scanf("%d %d\n", &n, &m);
a.clear();
x.clear();
a.resize(n+n+2);
for(i=0;i<n+n+2;i++) a[i].resize(n+n+2);
source=0;
sink=n+n+1;
x.resize(n+n+2);
for(i=0;i<m;++i)
{
scanf("%d %d\n", &p, &q);
if(!a[p][q+n])
{
a[p][q+n]=1;
x[p].push_back(q+n);
x[q+n].push_back(p);
}
}
for(i=1;i<=n;++i)a[source][i]=1, x[source].push_back(i), x[i].push_back(source);
for(i=n+1;i<sink;++i) a[i][sink]=1, x[i].push_back(sink), x[sink].push_back(i);
}
int bfs()
{
int Q[maxn<<1], p=1, q=1;
bool viz[maxn<<1];
//int d[maxn<<1];
memset(viz, 0,sizeof(viz));
//memset(t, -1, sizeof(t));
memset(d, 0, sizeof(d));
viz[source]=1;
Q[1]=source;
d[1]=0;
int u;
int i;
vector<int>::iterator it, xu;
while(p<=q)
{
u=Q[p++];
xu=x[u].end();
for(it=x[u].begin();it!=xu;++it)
{
i=*it;
if(!viz[i] && a[u][i])//(aa[u][(i)>>3]&(1<<((i)&7))))
{
viz[i]=1;
d[i]=d[u]+1;
// t[i]=u;
Q[++q]=i;
// if(i==sink) return d[i];
}
}
}
return d[sink];
}
int flow, ok=1, dsink,nr;
deque<nod>Q;
void dfs2(int nd, int nr)
{
// printf("%d %d\n",nd, nr);
if(nr>dsink) return;
if(nd==sink) { ++flow; ok=0; return;}
Viz[nd]=1;
vector<int>::iterator it, xnd;
int i;
xnd=x[nd].end();
for(it=x[nd].begin(); it!=xnd; ++it)
{
i=*it;
if(ok && !Viz[i] && a[nd][i])
{
dfs2(i, nr+1);
if(!ok)
{
a[nd][i]=0;
a[i][nd]=1;
// Viz[i]=1;
if(nd==source) ok=1;
else
break;
}
}
}
}
void dfs(int nd)
{
//if(nd!=sink) Viz[nd]=1;
// printf("%d %d\n", nd, nr);
if(nr>dsink) return;
if(nd==sink && nr==dsink) { ++flow; ok=0; return;}
Viz[nd]=1;
vector<int>::iterator it;
for(it=x[nd].begin();it!=x[nd].end();++it)
if(ok && !Viz[*it] && a[nd][*it])
{
++nr;
dfs(*it);
--nr;
if(!ok)
{
// a[nd][*it]=0;
//a[*it][nd]=1;
Q.push_back(nod(nd, *it));
if(nd==source) ok=1;
else break;
}
}
}
void DFS(int nd, int nr)
{
if(nr>dsink) return;
if(nd==sink) { ++flow; ok=0; return ;}
Viz[nd]=1;
vector<int>::iterator it;
for(it=x[nd].begin();it!=x[nd].end();++it)
if(d[nd]==d[*it]-1)
if(ok && !Viz[*it] && a[nd][*it])
{
DFS(*it, nr+1);
if(!ok)
{
a[nd][*it]=0;
a[*it][nd]=1;
// Q.push_back(nod(nd, *it));
if(nd==source) ok=1;
else break;
}
}
}
void solve()
{
int i, j;
int p;
flow=0;
vector<int>::iterator it;
int num=0;
int sq=(int)sqrt(n+n)+3;
int ntimes=0;
while(ntimes<sq)
{
dsink=bfs();
if(dsink==0) break;
++ntimes;
++num;
// printf("(%d)\n", dsink);
memset(Viz, 0, sizeof(Viz));
ok=1;
nr=0;
//dsink=d[sink];
// Viz[source]=1;
//Q.clear();
DFS(source, 0);
//for(deque<nod>::iterator p=Q.begin();p!=Q.end();++p)
// a[p->x][p->y]=0,
// a[p->y][p->x]=1;
}
printf("%d\n", 2*n-flow);
//printf("%d %d %d\n",(int) sqrt(n), nr, n);
//printf("(%d)\n", n);
// printf("(%d)\n", (int)sqrt(n+n)+3);
//printf("(%d)\n", num);
}
int main()
{
// freopen("fel.in", "r", stdin);
freopen(FIN, "r", stdin);
freopen(FOUT, "w", stdout);
read();
solve();
return 0;
}