#[derive(Clone,Copy,Eq,PartialEq,Debug)]
pub struct Vite(pub usize);

#[derive(Clone,Copy,Eq,PartialEq,Debug)]
pub struct Eite(pub usize);

pub trait Edge {
    fn from(&self) -> Vite;
    fn to(&self) -> Vite;
}

pub trait Vertex {
    fn new(id : usize) -> Self;
    fn id(&self) -> usize;
}

pub trait Graph<'a, V: Vertex, E: Edge> {
    type EsIter: std::iter::Iterator<Item=&'a Eite>;
    fn add_edge(&mut self, e: E);
    fn delta(&'a self, v: &Vite) -> Self::EsIter;
    fn edge(&self, e: &Eite) -> &E;
    fn vertex(&self, v: &Vite) -> &V;
    fn v_size(&self) -> usize;
    fn e_size(&self) -> usize;
}

pub fn from<E: Edge>(f: Vite, e: &E) -> Vite {
    if e.from() == f { e.from() }
    else { e.to() }
}

pub fn to<E: Edge>(f: Vite, e: &E) -> Vite {
    if e.from() == f { e.to() }
    else { e.from() }
}

pub trait Directed<'a,V: Vertex, E: Edge>: Graph<'a,V,E> {  }
pub trait Undirected<'a,V: Vertex, E: Edge>: Graph<'a,V,E> {  }
pub trait Bipartite<'a,V: Vertex, E: Edge>: Graph<'a,V,E> { 
    fn left_size(&self) -> usize;
    fn right_size(&self) -> usize;
    fn left_vs(&self) -> std::slice::Iter<Vite>;
    fn right_vs(&self) -> std::slice::Iter<Vite>;
}

pub struct BipartiteUndirectedGraph<V: Vertex, E: Edge> {
    le: usize,
    ri: usize,
    m: usize,
    g: Vec<Vec<Eite>>,
    es: Vec<E>,
    vs: Vec<V>,
    ls: Vec<Vite>,
    rs: Vec<Vite>
}

impl<'a, V: Vertex, E: Edge> Graph<'a,V,E> for BipartiteUndirectedGraph<V,E> {
    type EsIter = std::slice::Iter<'a,Eite>;
    fn add_edge(&mut self, e: E) { 
        assert!(e.from().0 < self.le);
        assert!(self.le <= e.to().0 && e.to().0 < self.le + self.ri);
        let ei = Eite(self.m);
        self.m += 1;
        self.g[e.from().0].push(ei);
        self.g[e.to().0].push(ei);
        self.es.push(e);
    }
    fn delta(&'a self, v: &Vite) -> Self::EsIter {
        self.g[v.0].iter()
    }
    fn edge(&self, e: &Eite) -> &E {
        &self.es[e.0]
    }
    fn vertex(&self, v: &Vite) -> &V {
       &self.vs[v.0]
    }
    fn v_size(&self) -> usize {
        self.le + self.ri
    }
    fn e_size(&self) -> usize {
        self.m
    }
}

impl<'a,V: Vertex, E: Edge> Undirected<'a,V,E> for BipartiteUndirectedGraph<V,E> {  }
impl<'a,V: Vertex, E: Edge> Bipartite<'a,V,E> for BipartiteUndirectedGraph<V,E> { 
    fn left_size(&self) -> usize { self.le }
    fn right_size(&self) -> usize { self.ri }
    fn left_vs(&self) -> std::slice::Iter<Vite> { self.ls.iter() }
    fn right_vs(&self) -> std::slice::Iter<Vite> { self.rs.iter() }
}

impl<V: Vertex, E: Edge> BipartiteUndirectedGraph<V,E> {
     pub fn new(le: usize, ri: usize) -> BipartiteUndirectedGraph<V,E> { 
         BipartiteUndirectedGraph { 
             le: le,
             ri: ri,
             m: 0,
             g: vec![Vec::<Eite>::new(); le + ri],
             es: Vec::<E>::new(),
             vs: Vec::<V>::new(),
             ls: (0..le).map(|i| Vite(i)).collect(),
             rs: (le..le+ri).map(|i| Vite(i)).collect()
         }
     }
}


use std::collections::vec_deque::*;

pub fn hk_dfs<'a,V,E,G>(g:&'a G, v: &Vite, dist: &mut Vec<i32>, mate: &mut Vec<Option<usize>>, used: &mut Vec<bool>, vis: &mut Vec<bool>) -> bool
where V: Vertex, E: Edge, G: Bipartite<'a,V,E> + Undirected<'a,V,E> {
    vis[v.0] = true;
    for e in g.delta(v) {
        let to = to(*v, g.edge(e));
        let ok = match mate[to.0] {
            Some(m) => {
                if !vis[m] && dist[m] == dist[v.0] + 1 && hk_dfs(g,&Vite(m),dist,mate,used,vis) {
                    true
                }
                else {
                    false
                }
            }
            None => {
                true
            }
        };
        if ok {
            mate[to.0] = Some(v.0);
            used[v.0] = true;
            return true;
        }
    }

    false
}

pub fn hopcroft_karp<'a,V,E,G>(g: &'a G) -> Vec<(Vite,Vite)>
where V: Vertex, E: Edge, G: Bipartite<'a,V,E> + Undirected<'a,V,E> {
    let mut ans = Vec::<(Vite,Vite)>::new();
    let n = g.v_size();
    
    let mut mate: Vec<Option<usize>> = vec![None;n];
    let mut used = vec![false;n];

    loop {
        let mut vis = vec![false;n];
        let mut dist = vec![-1;n];
        let mut que = VecDeque::new();

        for i in 0..n {
            if !used[i] {
                que.push_back(i);
                dist[i] = 0;
            }
        }

        while let Some(v) = que.pop_front() {
            for e in g.delta(&Vite(v)) {
                let to = to(Vite(v), g.edge(e));
                if let Some(m) = mate[to.0] {
                    if dist[m] == -1 {
                        dist[m] = dist[v] + 1;
                        que.push_back(m);
                    }
                }
            }
        }

        let mut has_end = true;
        for i in g.left_vs() {
            if !used[i.0] && hk_dfs(g,i,&mut dist,&mut mate,&mut used,&mut vis) {
                has_end = false;
            }
        }
        if has_end {
            break;
        }
    }

    for i in g.right_vs() {
        if let Some(m) = mate[i.0] {
            ans.push((i.clone(),Vite(m)));
        }
    }
    ans
}
struct Ver {
    i: usize
}
  
impl Vertex for Ver {
    fn new(id: usize) -> Self {
        Ver {
            i: id
        }
    }
    fn id(&self) -> usize { self.i }
}
  
struct WEdge {
    from: Vite,
    to: Vite,
}
  
impl Edge for WEdge {
    fn from(&self) -> Vite { self.from } 
    fn to(&self) -> Vite { self.to }
}
  
fn main() {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).unwrap();
    let v:Vec<usize> = s.trim().split_whitespace()
        .map(|e|e.parse().unwrap()).collect();
    let (a,b,e) = (v[0] , v[1] , v[2]);
    let mut g = BipartiteUndirectedGraph::<Ver, WEdge>::new(a,b);
    for _ in 0..e{
        let mut t = String::new();
        std::io::stdin().read_line(&mut t).unwrap();
        let x:Vec<usize> = t.trim().split_whitespace()
            .map(|e|e.parse().unwrap()).collect();
        let (v,u) = (x[0],a + x[1]);
        g.add_edge(WEdge{ from: Vite(v), to: Vite(u) });
    }
    let res = hopcroft_karp(&g);
    println!("{}",res.len());
}



Measured memory_bytes: 5056