#include<bits/stdc++.h>
using namespace std;

#include<vector>
#include<utility>
#include<vector>
#include<queue>

namespace ProconLib{
    
    template<typename cap_t,cap_t INF,typename edge_t>
    class FlowImpl{
        protected:
        using Edges=std::vector<edge_t>;
        using Graph=std::vector<Edges>;
        int N;
        Graph g;
        std::vector<int> level;
        std::vector<int> iter;
        void bfs(int s);
        cap_t dfs(int v,int t,cap_t f);
        FlowImpl(int N):N(N),g(N){};
    };

    template<typename cap_t,cap_t INF,typename edge_t>
    void FlowImpl<cap_t,INF,edge_t>::bfs(int s){
        level.assign(N,-1);
        std::queue<int> que;
        level[s]=0;
        que.push(s);
        while(!que.empty()){
            int v=que.front(); que.pop();
            for(int i=0;i<g[v].size();i++){
                edge_t &e=g[v][i];
                if(e.cap>0 && level[e.to]<0){
                    level[e.to]=level[v]+1;
                    que.push(e.to);
                }
            }
        }
    }
    template<typename cap_t,cap_t INF,typename edge_t>
    cap_t FlowImpl<cap_t,INF,edge_t>::dfs(int v,int t,cap_t f){
        if(v==t) return f;
        for(int& i=iter[v];i<g[v].size();i++){
            edge_t& e=g[v][i];
            if(e.cap>0 && level[v]<level[e.to]){
                cap_t d=dfs(e.to,t,std::min(f,e.cap));
                if(d>0){
                    e.cap-=d;
                    g[e.to][e.rev].cap+=d;
                    return d;
                }
            }
        }
        return 0;
    }
}
namespace ProconLib{
    template<typename T>
    struct EdgeForMaximumFlow{
        int to;
        T cap;
        int rev;
        EdgeForMaximumFlow(int to,T cap,int rev):to(to),cap(cap),rev(rev){}
    };

    template<typename cap_t=long long,cap_t INF=cap_t(1e9+9)>
    class MaximumFlow:protected FlowImpl<cap_t,INF,EdgeForMaximumFlow<cap_t>>{
        protected:
        using Edge=EdgeForMaximumFlow<cap_t>;
        using Super=FlowImpl<cap_t,INF,Edge>;
        using Super::N;
        using Super::g;
        using Super::level;
        using Super::iter;
        using Super::bfs;
        using Super::dfs;
        public:
        MaximumFlow(int N):Super(N){}
        void addEdge(int from,int to,cap_t cap);
        cap_t maximumFlow(int s,int t);
    };

    template<typename cap_t,cap_t INF>
    cap_t MaximumFlow<cap_t,INF>::maximumFlow(int s,int t){
        cap_t flow=0;
        while(true){
            bfs(s);
            if(level[t]<0) return flow;
            iter.assign(N,0);
            cap_t f;
            while((f=dfs(s,t,INF))>0){
                flow+=f;
            }
        }
    }
    template<typename cap_t,cap_t INF>
    void MaximumFlow<cap_t,INF>::addEdge(int from,int to,cap_t cap){
        g[from].push_back(Edge(to,cap,int(g[to].size())));
        g[to].push_back(Edge(from,cap_t(0),int(g[from].size())));
    }
}
namespace ProconLib{

    class BipartiteMatching:private MaximumFlow<int>{
        using Super=MaximumFlow<int>;
        using Super::g;
        int N,M;
        int S,T;
        int matchNum=0;
        int X(int id){return id;}
        int Y(int id){return N+id;}
        int inverseY(int id){return id-N;}
        public:
        BipartiteMatching(int N,int M);
        void addEdge(int x,int y){Super::addEdge(X(x),Y(y),1);}
        int match(){return matchNum+=maximumFlow(S,T);}
        std::vector<std::pair<int,int>> getMatches();
    };

    BipartiteMatching::BipartiteMatching(int N,int M):N(N),M(M),S(N+M),T(N+M+1),Super(N+M+2){
        for(int i=0;i<N;i++) Super::addEdge(S,X(i),1);
        for(int i=0;i<M;i++) Super::addEdge(Y(i),T,1);
    }
    std::vector<std::pair<int,int>> BipartiteMatching::getMatches(){
        std::vector<std::pair<int,int>> res;
        for(int i=0;i<N;i++){
            for(auto& e:g[X(i)]){
                if(e.to!=S && e.cap==0){
                    res.push_back(std::pair<int,int>{i,inverseY(e.to)});
                }
            }
        }
        return res;
    }
}using namespace ProconLib;
int main(){
    int X,Y,E;
    cin>>X>>Y>>E;
    BipartiteMatching bm(X,Y);
    for(int i=0;i<E;i++){
        int x,y;
        cin>>x>>y;
        bm.addEdge(x,y);
    }

    cout<<bm.match()<<endl;
    
    return 0;
}



Measured memory_bytes: 3264