二分图学习

Posted cynchanpin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二分图学习相关的知识,希望对你有一定的参考价值。

图论中的难见就是建图然后套用算法。

特点:
仅仅能一一相应,即XX仅仅能有一个人。
先来一个比較好的入门资料二分图最大匹配 參考 二分图建图方法

算法的思路是不停的找增广路径, 并添加匹配的个数,增广路径顾名思义是指一条能够使匹配数变多的路径,在匹配问题中,增广路径的表现形式是一条”交错路径”,也就是说这条由图的边组成的路径。 它的第一条边是眼下还没有參与匹配的,第二条边參与了匹配。第三条边没有..最后一条边没有參与匹配,而且始点和终点还没有被选择过。这样交错进行,显然他有奇数条边。

那么对于这样一条路径,我们能够将第一条边改为已匹配。第二条边改为未匹配…以此类推。

也就是将全部的边进行”反色”,easy发现这样改动以后,匹配仍然是合法的,但是匹配数添加了一对。另外。单独的一条连接两个未匹配点的边显然也是交错路径。能够证明。当不能再找到增广路径时,就得到了一个最大匹配,这也就是匈牙利算法的思路。


3个重要结论:
最小点覆盖数: 最小覆盖要求用最少的点(X集合或Y集合的都行)让每条边都至少和当中一个点关联。

能够证明:最少的点(即覆盖数)=最大匹配数
最小路径覆盖=最小路径覆盖=|N|-最大匹配数
用尽量少的不相交简单路径覆盖有向无环图G的全部结点。解决此类问题能够建立一个二分图模型。把全部顶点i拆成两个:X结点集中的i和Y结点集中的i’。假设有边i->j,则在二分图中引入边i->j’,设二分图最大匹配为m,则结果就是n-m。
二分图最大独立集=顶点数-二分图最大匹配
在N个点的图G中选出m个点,使这m个点两两之间没有边。求m最大值。


假设图G满足二分图条件,则能够用二分图匹配来做.最大独立集点数 = N - 最大匹配数。

做题见过的几种建图方案:
1. 二维矩阵中,1X2的方格覆盖将图看成国际象棋那种黑白相间
2. 2015上海邀请赛热身题B看成一直黑白相间下去的二分图
3. 有向无环图,每条边相连的两点看成二分图的两部分
4. 二维矩阵中。每行每列 仅仅能放一个。将X坐标集合看成一部分。Y看成一部分。

交点有ship的时候相应的行和列才不能够放,就是说你选了相应的行,相当于相应的列也被选择。然后这不就是一种匹配吗,所以我们就能够依据这种性质来建立二部图。从而转化成求二部图最大匹配的问题。
将横着的没有被阻挡的块合并成一个大块。将竖着的没有被阻挡的块合并成一个大块。

这样得到若干个横向块。和纵向块。假设一横向块与纵向块之间有共同的点。那么就将这两个大块连线(构造一个横向块与纵向块的邻接矩阵)。

构造好之后就能够算横向块与纵向块的最大匹配数。

(HDU 5093 ZOJ 1654 ZOJ 3156)
5. 最小路径覆盖问题,原始的最小路径覆盖的各个路径是不能有同样的点的,假设是但是可相交的路径覆盖就要先求一次闭包。poj 2594 參考


模板

#include <stdio.h>
#include <string.h>
#define MX 155
int n, m;
bool g[MX][MX], v[MX];
int match[MX];

bool find(int x) {
    for(int i = 1; i <= n; ++i) {
        if(!v[i] && g[x][i]) {
            v[i] = 1;
            if(match[i] == -1 || find(match[i])) {
                match[i] = x;
                return 1;
            }
        }
    }
    return 0;
}

void hungary() {
    int ans = 0;
    for(int i = 1; i <= n; ++i) {
        memset(v, 0, sizeof(v));
        if(find(i)) ans ++;
    }
    printf("%d\\n", n - ans);
}
int main() {
    int cas;
    scanf("%d", &cas);
    while(cas --) {
        while (scanf("%d%d", &n, &m) != EOF) {
            memset(g, 0, sizeof(g));
            memset(match, -1, sizeof(match));
            int a, b;
            for(int i = 1; i <= m; ++i) {
                scanf("%d%d", &a, &b);
                g[a][b] = 1;
            }
            hungary();
        }
    }
    return 0;
}

以上是关于二分图学习的主要内容,如果未能解决你的问题,请参考以下文章

二分图学习

二分图匹配-匈牙利算法学习

二分图算法手把手教你学会:染色法(判断二分图)匈牙利算法(二分图的最大匹配)

二分图相关问题

km算法(二分图最大权匹配)学习

hihoCoder 1393 网络流三·二分图多重匹配 (网络流学习#3 记录)