二分图匹配



 

#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,分为二分图的左侧和右侧。
    优先选择左侧序号更小的连接可能的边。
    对于两个点的目标点“冲突”的时候,采取“协商”的办法。
    即序号小的连接可能连接的另一条边。
    若“协商”失败,则放弃序号较大的点的边。
不存在十全十美的文章 如同不存在彻头彻尾的绝望
原文地址:https://www.cnblogs.com/qf-breeze/p/10526881.html