zoukankan      html  css  js  c++  java
  • 二分图最大匹配简要整理

     部分内容引自xht37的博客



    图的匹配

    对于无向图$G=(V,E),Msubseteq L$,若$M$中任意两条边没有公共点,则称该边集$M$为图$G$的一个匹配

    定义匹配的大小为边的数量$|M|$,其中边数最大的$M$为最大匹配

    无法再增加匹配边的匹配为极大匹配

    显然极大匹配不一定是最大匹配,但最大匹配一定是极大匹配

    匹配$M$中的边称为M-匹配边,未匹配的边称为M-未匹配边

    一个点如果为$M$中匹配边的端点则称为M-匹配点(M-饱和点),否则称为M-未匹配点(M-未饱和点)

    若图$G$中每个结点都是M-匹配点则称$M$为完美匹配(完全匹配)

    完美匹配是最大匹配,但最大匹配不一定是完美匹配

    若图中节点个数为奇数且刚好只有一点是M-未匹配点则称$M$为近完美匹配

    增广路

    对于匹配$M$,由匹配边和非匹配边交替构成的路径称为M-交错路

    显然交错路一定为简单路

    M-交错回路:满足回路和交错路条件的路径

    若M-交错路的始点和终点都是M-未匹配点则称该交错路为M-增广路

    性质:

    1,图$G$的匹配$M$为最大匹配,当且仅当$G$中不含M-增广路

    2,如果把路径上所有边的状态(是否为匹配边)取反,那么得到的新的边集 仍然是一组匹配,并且匹配的边数增加了1

    二分图

    二分图:节点由两个集合组成,且两个集合内部没有边的图

    性质:不含奇环

    完备匹配:$|M|=min{|V1|,|V2|},V1,V2$为二分图两点集

    完备匹配是最大匹配,但最大匹配不一定是完备匹配

    Hall定理

    判定二分图存在完备匹配的充要条件:当且仅当任取$V1$一子集$S$,有$|N(S)>=S|$,$N(S)$表示与$S$中各结点相邻的所有节点的集合

    匈牙利算法

    思想:

    不断寻找增广路,并把增广路上所有边的状态取反,得到一个更大的匹配,直到图中不存在增广路

    过程:

    依次尝试给每一个左部点$x$寻找一个匹配的右部点$y$

    $y$与$x$匹配需满足下面两个条件之一:

    1,$y$是非匹配点。

    2,$y$已与$i$匹配,但从$i$出发能找到另一个$j$与之匹配

    时间复杂度$O(nm)$

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int maxn=1010;
    struct edge{
        int next,to;
    }e[maxn*maxn];
    int n,m,ed,head[maxn],cnt,ans,pre[maxn];
    bool vis[maxn];
    void add(int x,int y)
    {
        e[++cnt].next=head[x];
        e[cnt].to=y;
        head[x]=cnt;
    }
    bool dfs(int x)
    {
        for(int v,i=head[x];i;i=e[i].next)
            if(!vis[v=e[i].to])
            {
                vis[v]=1;
                if(!pre[v]||dfs(pre[v]))
                {
                    pre[v]=x;
                    return 1;
                }
            }
        return 0;
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&ed);
        for(int x,y,i=1;i<=ed;i++)
        {
            scanf("%d%d",&x,&y);
            add(x,y);
        }
        for(int i=1;i<=n;i++)
        {
            memset(vis,0,sizeof(vis));
            if(dfs(i))
                ans++;
        }
        printf("%d
    ",ans);
        return 0;
    }


    二分图多重匹配

    定义:从二分图中选出尽量多的边,使任取点$v$满足$v$作为最多$a_v$条选出的边的端点,则称选出的边集为二分图的多重匹配

    解法:拆点进行二分图最大匹配(将点$v$拆成$a_v$个点)

    二分图最小点覆盖

    图的点覆盖:对于一张无向图$(V,E)$,若存在一个点集$V'$,满足$V'⊆V$,且对于任意$e∈E$,$e$至少有一个端点属于$V'$,则称$V'$为这张无向图的一组点覆盖

    二分图最小点覆盖:在二分图中,包含点数最少的一组点覆盖被称为二分图的最小点覆盖

    定理:二分图最小点覆盖包含的点数,等于最大匹配包含的边数

    二分图最大独立集

    图的独立集:对于一张无向图$(V,E)$,若存在一个点集$V'$,满足$V'⊆V$,且对于任意$p,q∈V'$,$(p,q)∉E$,则称$V'$为这张无向图的一组独立集,包含点数最多的独立集被称为图的最大独立集

    定理:二分图最大独立集包含的点数,等于$n-$最大匹配包含的边数

    有向无环图的最小路径点覆盖

    给定一张有向无环图,用尽量少的不相交的简单路径覆盖所有点(也就是每个点恰好被覆盖一次),这样的路径集合被称为最小路径点覆盖

    拆点二分图

    把每个点拆成编号为$x$和$x+n$的两个点

    建立一张新的二分图,$1∼n$是左部点,$n+1∼2n$是右部点。

    对原图的每条有向边$(x,y)$,在二分图的左部点$x$与右部点$y+n$之间连边

    最终得到的二分图成为原图的拆点二分图

    定理:有向无环图的最小路径点覆盖包含的路径条数,等于$n-$拆点二分图的最大匹配边数

    证明:在最小路径点覆盖的方案中,因为所有路径不相交,所以每一个点的入度和出度都不超过1;因为每个节点都被覆盖,所以x的出度和入度至少有一个是1。因此,最小路径点覆盖中的所有边,在拆点二分图中构成一组匹配。最小路径覆盖中每条边(x,y)的起点x与二分图每条匹配边(x,y+n)的左部点x是一一对应的。特别地,对于每条路径的终点t,因为t没有出边,所以出度为0,对应在二分图中就是t匹配失败。即路径的终点和二分图左部的非匹配点是一一对应的。故而,G的最小路径点覆盖等于n减去最大匹配数。

    可重复最小路径点覆盖

    对原图进行传递闭包,按照普通最小路径点覆盖处理即可

  • 相关阅读:
    学生管理
    数据类型
    Linux安装、发布Django项目
    函数式编程
    学生管理系统
    mysql数据库工具类
    python操作数据库
    链接mysql建库建表
    列表元组字典集合
    内置对象相关方法
  • 原文地址:https://www.cnblogs.com/ivanovcraft/p/14600667.html
Copyright © 2011-2022 走看看