• 二分图学习


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

    特点:
    仅仅能一一相应,即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 - 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;
    }
  • 相关阅读:
    AngularJS各种'service'的区别
    js 斐波那契数列实现
    Mac下Apache+MySQL+PHP开发环境安装过程
    原生封装的js前端工具库(包含了jquery的常用功能)
    BFC 神奇背后的原理
    CSS清浮动处理(Clear与BFC)
    JavaScript实现 页面滚动图片加载(懒加载)
    CodeForce 814B
    排序算法
    uva1610
  • 原文地址:https://www.cnblogs.com/cynchanpin/p/7163341.html
Copyright © 2020-2023  润新知