#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <climits>
using namespace std;
const int MAXN = 100 + 5;
//int n, m;
struct Node {
vector<struct Edge> edges;
int level;
struct Edge *curE;
} N[MAXN];
struct Edge {
Node *from, *to;
int flow, cap, rev;
Edge(Node *from, Node *to, int cap, int rev) : from(from), to(to), cap(cap), flow(0), rev(rev) {}
};
inline void addEdge(int u, int v, int cap)
{
N[u].edges.push_back(Edge(&N[u], &N[v], cap, N[v].edges.size()));
N[v].edges.push_back(Edge(&N[v], &N[u], 0, N[u].edges.size() - 1));
}
struct Dinic {
inline bool makeLevelGraph(Node *s, Node *t, int n)
{
for (int i = 0; i < n; i++)
{
N[i].curE = &N[i].edges.front();
N[i].level = 0;
}
queue<Node *> q;
q.push(s);
s->level = 1;
while (!q.empty())
{
Node *v = q.front();
q.pop();
for (Edge *e = &v->edges.front(); e && e <= &v->edges.back(); e++)
{
if (e->flow < e->cap && !e->to->level)
{
e->to->level = v->level + 1;
if (e->to == t) return true;
else q.push(e->to);
}
}
}
return false;
}
int findPath(Node *s, Node *t, int limit = INT_MAX)
{
if (s == t) return limit;
for (Edge *&e = s->curE; e && e <= &s->edges.back(); e++)
{
if (e->flow < e->cap && e->to->level == s->level + 1)
{
int flow = findPath(e->to, t, e->cap - e->flow);
if (flow)
{
e->flow += flow;
e->to->edges[e->rev].flow -= flow;
return flow;
}
}
}
return 0;
}
int operator()(int s, int t, int n)
{
int res = 0;
while (makeLevelGraph(&N[s], &N[t], n))
{
int flow;
while ((flow = findPath(&N[s], &N[t])) > 0)
{
res += flow;
}
}
return res;
}
} dinic;
/*void solve()
{
int S = 0, T = z + 1;
} */
int main()
{
int z, x;
scanf("%d %d", &z, &x);
int a, b;
while (scanf("%d %d", &a, &b) == 2)
{
//if (a == 0 && b == 0) break;
addEdge(a, b, INT_MAX);
}
//solve();
int S = 0, T = z + 1;
for (int i = 1; i <= x; i++)
{
addEdge(S, i, 1);
}
for (int i = x + 1; i <= z; i++)
{
addEdge(i, T, 1);
}
int ans = dinic(S, T, z + 2);
printf("%d\n", ans);
return 0;
}
普通边连容量为INT_MAX的边,左边和源S连容量为1的边,右边和汇T连容量为1的边,跑最大流即可。