Problem:
Bipartite Matching A bipartite graph G = (V, E) is a graph in which the vertex set V can be divided into two disjoint subsets X and Y such that every edge e ∈ E has one end point in X and the other end point in Y . A matching M is a subset of edges such that each node in V appears in at most one edge in M . Given a bipartite graph, find the size of the matching which has the largest size. Input  |X|  |Y|  |E|  x 0  y 0  x 1  y 1 : x |E|-1  y |E|-1   |X| and |Y| are the number of vertices in X and Y respectively, and |E| is the number of edges in the graph G . The vertices in X are named with the numbers 0, 1,..., |X| -1, and vertices in Y are named with the numbers 0, 1,..., |Y| -1, respectively.  x i and y i are the node numbers from X and Y respectevely which represent the end-points of the i -th edge. Output Print the largest size of the matching. Constraints  1 ≤ |X| , |Y| ≤ 100  0 ≤ |E| ≤ 10,000  Sample Input 1 3 4 6
0 0
0 2
0 3
1 1
2 1
2 3 Sample Output 1 3

Solution (Python):

from collections import deque
class HopcroftKarp:
    def __init__(self, N0, N1):
        self.N0 = N0
        self.N1 = N1
        self.N = N = 2+N0+N1
        self.G = [[] for i in range(N)]
        for i in range(N0):
            forward = [2+i, 1, None]
            forward[2] = backward = [0, 0, forward]
            self.G[0].append(forward)
            self.G[2+i].append(backward)
        self.backwards = bs = []
        for i in range(N1):
            forward = [1, 1, None]
            forward[2] = backward = [2+N0+i, 0, forward]
            bs.append(backward)
            self.G[2+N0+i].append(forward)
            self.G[1].append(backward)

    def add_edge(self, fr, to):
        
        
        v0 = 2 + fr
        v1 = 2 + self.N0 + to
        forward = [v1, 1, None]
        forward[2] = backward = [v0, 0, forward]
        self.G[v0].append(forward)
        self.G[v1].append(backward)

    def bfs(self):
        G = self.G
        level = [None]*self.N
        deq = deque([0])
        level[0] = 0
        while deq:
            v = deq.popleft()
            lv = level[v] + 1
            for w, cap, _ in G[v]:
                if cap and level[w] is None:
                    level[w] = lv
                    deq.append(w)
        self.level = level
        return level[1] is not None

    def dfs(self, v, t):
        if v == t:
            return 1
        level = self.level
        for e in self.it[v]:
            w, cap, rev = e
            if cap and level[v] < level[w] and self.dfs(w, t):
                e[1] = 0
                rev[1] = 1
                return 1
        return 0

    def flow(self):
        flow = 0
        N = self.N; G = self.G
        bfs = self.bfs; dfs = self.dfs
        while bfs():
            *self.it, = map(iter, G)
            while dfs(0, 1):
                flow += 1
        return flow

    def matching(self):
        return [cap for _, cap, _ in self.backwards]


import sys
readline = sys.stdin.readline
write = sys.stdout.write

X, Y, E = map(int, readline().split())

hc = HopcroftKarp(X, Y)
for i in range(E):
    x, y = map(int, readline().split())
    hc.add_edge(x, y)

write("%d\n" % hc.flow())

Solution (Python):
xn, yn, e = map(int, input().split())
edges = [set() for _ in range(xn)]
matched = [-1] * yn

def dfs(v, visited):
    for u in edges[v]:
        if u in visited:
            continue
        visited.add(u)
        if matched[u] == -1 or dfs(matched[u], visited):
            matched[u] = v
            return True
    return False

for _ in range(e):
    x, y = map(int, input().split())
    edges[x].add(y)

print(sum(dfs(s, set()) for s in range(xn)))