#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
inline LL read () {
LL res = 0 ;
int f (1) ;
char ch = getchar ();
while (!isdigit(ch)) {
if (ch == '-') f = -1 ;
ch = getchar();
}
while (isdigit(ch)) res = (res << 1) + (res << 3) + (ch ^ 48),ch = getchar();
return res * f ;
}
const int N = 1e3;
bool f[N][N];
bool used[N];
int match[N];
int n,m,e;
inline bool DFS(int pos) {
for(register int i=1; i<=m; i++) {
if(f[pos][i] and !used[i]) {
used[i] = true;
if(!match[i] or DFS(match[i])) {
match[i] = pos;
return true;
}
}
}
return false;
}
signed main() {
n=read(),m=read(),e=read();
for(register int i=1; i<=e; i++) {
int x=read(),y=read();
if(x<=n and y<=m) f[x][y] = true;
}
int ans = 0;
for(register int i=1; i<=n; i++) {
memset(used,false,sizeof(used));
if(DFS(i)) ans++;
}
cout << ans << endl ;
return 0;
}
一、二分图
对于一个图G=(V,E),若能将其点集分为两个互不相交的两个子集X、Y,
使得X∩Y=∅,且对于G的边集V,若其所有边的顶点全部一侧属于X,
一侧属于Y,则称图G为一个二分图。
二、定理:
当且仅当无向图G的回路个数为偶数时,图G为一个二分图。
无回路的图也是二分图。
三、二分图判定:
在二分图G中,任选一个点V,
使用BFS算出其他点相对于V的距离(边权为1)
对于每一条边E,枚举它的两个端点,若其两个端点的值,
一个为奇数,一个为偶数,则图G为一个二分图。
四、匹配:
对于一个二分图G的子图M,若M的边集E的的任意两条边都不连接同一个顶点,
则称M为G的一个匹配。
五、最大匹配
对于二分图G的一个子图M,若M为其边数最多的子图,
则称M为G的最大匹配。
六、匈牙利算法
1、算法描述:
建立有向图G,分为二分图的左侧和右侧。
优先选择左侧序号更小的连接可能的边。
对于两个点的目标点“冲突”的时候,采取“协商”的办法。
即序号小的连接可能连接的另一条边。
若“协商”失败,则放弃序号较大的点的边。