// ???????????????????????°?????? BigraphInConstruct.h
int tail[emaxsize+1], head[emaxsize+1];
int edgefirst[vmaxsize+1], edgenext[emaxsize+1];
int match[vmaxsize+1];  // ???v?????\?¶?????????????????????°??????match[v]
int m, n, n1, n2;       // ?????´????????°n1????????´????????°n2???n=n1+n2




// ???????????????????????°??????LevelConstruct.h
int level[vmaxsize+1];  // ??¬????????°?????????????????????v?????¬??????level[v]
int queue[vmaxsize+1];  // ???????????¢?´¢?????????????????\???
int max_level;          // ????????????????????????????????´?????????????°???¬??????
int t_found;            // ????????????????????????????????´???????????°???????????¨???t_found=true
int front, rear;        // ?????\????????????front??¨????°?rear

// ???????????????????????°?????? Augmentation.h
int parent[vmaxsize + 1]; // ??±???????????¢?´¢??¨???????????????v??????parent[v]
int pathfound, pathend;   // ?¢??????????????????¨ (pathfound=true)???pathend????????´?????????

// Hopcroft-Karp????????§??????????????°????±???????????????°?????? hopkarp.c
#include <stdio.h>
#define vmaxsize         1000
#define emaxsize         4000
#define unvisited          -1
#define undefined          -1
#define noparent            0
#define free                0
#define false               0
#define true                1
#include"BigraphInConstruct.h" // ???????????????BigraphInConstruct.h???????????????
#include"LevelConstruct.h"     // ???????????????????????°??????LevelConstruct.h???????????????
#include"Augmentation.h"       // ???????????????????????°??????Augmentation.h???????????????
void bipartite_graph_input(void){
    int a;
    scanf("%d %d %d", &n1, &n2, &m);
    n=n1+n2; // n?????°??????????????°
    for (a = 1; a <= m; a++) {
        scanf("%d %d", &tail[a], &head[a]);
    }
}
void bipartite_incidence_list_construct(void){
    int a, v1;
    for (v1 = 1; v1 <= n1; v1++) edgefirst[v1] = 0;
    for (a = m; a >= 1; a--) {
        v1 = tail[a];
        edgenext[a] = edgefirst[v1];
        edgefirst[v1] = a;
    }
}
void matching_output(void){
    int a, v1, k;
    k=0; 
    for (v1 = 1; v1 <= n1; v1++) {
        if (match[v1] != free) {
            k++;
        }
    }
    printf("%d\n, k);
}

void bipartite_bfs(int v1){// ?????´??????v1??????????????¨??°????????§??????????????¢?´¢
    int v2, w1;
    int a,b;
    for(a = edgefirst[v1]; a != 0; a = edgenext[a]) {// v1?????\?¶???????????????????????????????????????????????????§??\????????°?????????
        v2 = head[a]; // a????????´??????v1???????????´??????v2???????????????????????¨?????????
        if(level[v2] != unvisited){ // ?????´??????v2????¨???????????????¨???????????????????????????
            ;
        }else{// v2????????´????????§??????????¨????
            level[v2] = level[v1] + 1;
            if (t_found == n + 2){// ?¢??????????????????????????????£????????????
                if (match[v2] != free) {// v2???????????????????????????
                    b = match[v2]; // ??????????????°??????b
                    w1 = tail[b]; // b????????????v2???????????????w1???????????????????????????
                    level[w1] = level[v2] + 1; 
                    queue[++rear] = w1;
                }
                else {// v2???????????????????????????????????§v1??????v2????????????????¢??????????
                    t_found = rear + 1; // t_found<n+2 ????¢??????????????????¨?????????
                    max_level = level[v2];
                }
            }
        }
    }
}
void levelgraph(void){// ??¬????????°??????????§????
    int v,v1;
    rear = 0;    // ?????\???????????????
    front = 1;
    t_found=n+2; // ?¢?????????????????????????????????????????????¨???????¨????
    for (v = 1; v <= n; v++) level[v] = unvisited; // ????????????????¨??????¨???????¨????
    for (v1 = 1; v1 <= n1; v1++) {
        if (match[v1] == free) {// v1???????????????????????????????????´??????
            level[v1] = 0; // v1??????????????¨??°????????????????????¢?´¢????????§????????????
            queue[++rear] = v1; //?????\???queue???????°????v1????????\
        }
    }



    while (front < t_found) {// ?¢???????????????????????????????????????????
        if (front != rear + 1) {// ?????\???queue????????§??????????????°?????????
            v1 = queue[front++]; // ?????\?????????????????????v1?????????
            bipartite_bfs(v1); //v1??????????????¨??°????????????????????¢?´¢????§?
        }
        else {// ?????\???queue????????§???????????§???while?????????????????¶????????????
            break;
        }
    }


    
}
void bipartite_dfs(int v1)
{ // ?????´??????v1??????????????¨??°????????§?????±???????????¢?´¢
    int v2, w1;
    int a, b;
    for (a = edgefirst[v1]; a != 0; a = edgenext[a])
    {                 // v1?????\?¶???????????????????????????????????????????????????§??\????????°?????????
        v2 = head[a]; // a????????´??????v1???????????´??????v2???????????????????????¨?????????
        if (parent[v2] == undefined && level[v2] == level[v1] + 1)
        {
            parent[v2] = a; // a????????´??????v2?????????????????´??????v1???????????¨?????????
            if (level[v2] != max_level)
            {                   // v2????????´????????§????????????????????????
                b = match[v2];  // ??????????????°??????b
                w1 = tail[b];   // b????????????v2???????????????w1?????????????????????????????¨?????????
                parent[w1] = b; // b????????´??????w1????????????v2?????????
                bipartite_dfs(w1);
                if (pathfound)
                    return; //Added by Goro Satake
            }
            else
            { // level[v2] == max_level
                if (match[v2] == free)
                {                     // v2????????´????????§???????????????????????????
                    pathend = v2;     // ?¢??????????????????????v2
                    pathfound = true; // ?¢????????????????
                    return;           // ?¢????????????????????????°?????¶????????????????????±??????????????????????±????????????????
                }
            }
        }
    }
}
void augmentation(void)
{
    int v, v1, v2, w1;
    int a, b;
    for (v = 1; v <= n; v++)
        parent[v] = undefined;
    for (v1 = 1; v1 <= n1; v1++)
    {
        if (match[v1] != free)
        {
            continue;
        }
        else
        {                          // v1???????????????????????????????????´??????
            pathfound = false;     // v1??????????¢???????????????¢?´¢
            parent[v1] = noparent; // v1???????????±???????????¢?´¢??¨?????????v1
            bipartite_dfs(v1);     // v1???????????±?????????
            if (!pathfound)
            {
                continue;
            }
            else
            {                   // v1???????????±???????????§pathend???????¢????????????????
                v2 = pathend;   // ??±???????????¢?´¢??¨??§pathend???????????????v1?????§?????????
                a = parent[v2]; // ????????????????????????????????°?????¨?????????????????°????????????
                match[v2] = a;
                w1 = tail[a];
                match[w1] = a;
                while (w1 != v1)
                {
                    b = parent[w1];
                    v2 = head[b];
                    a = parent[v2];
                    match[v2] = a;
                    w1 = tail[a];
                    match[w1] = a;
                }
            }
        }
    }
}
int main(void){
    int v;
    bipartite_graph_input(); 
    // ?????¨??°??????????????°m????????´?????°n1????????´?????°n2?????????????§?????????????????±?????????????
    bipartite_incidence_list_construct(); // ??\?¶?????????????????§?????????????
    for (v = 1; v <= n; v++) match[v] = free; // ?????´??????????????????????????????????????????
    levelgraph();
    while(t_found != n + 2){
        augmentation();
        levelgraph();
    }
    matching_output(); // ??????????????????????????°?????????
    return 0;
}