模板总结——二分图最大权匹配

10人阅读 评论(0) 收藏 举报
分类:

基本概念

完全二分图:两侧顶点集大小相等的二分图

完备匹配:所有顶点都是匹配点的匹配

最大权匹配:在带权的完全二分图中,匹配边的权值和最大的完美匹配。

相等子图:由原图的点集和边权等于顶点标号的和的边集组成的图。

KM算法原理

设左侧顶点的顶标集为{Ui},右侧顶点的顶标集为{Vj}。

定理:如果含有顶标的二分图的相等子图存在完备匹配,则该匹配就是原图的最大权匹配。

KM算法通过不断地调整{Ui}和{Vj},直到其相等子图存在一个完备匹配,然后用匈牙利算法求出这个完备匹配。

KM算法流程

流程:
(1)初始化可行顶标的值
(2)用匈牙利算法寻找完备匹配
(3)若未找到完备匹配,则修改可行顶标的值
(4)重复(2)(3)直到找到相等子图的完备匹配为止

伪代码:
(1)左侧顶标设为所有相连边的最大边权,右侧顶标设为0
(2)对应图左侧的每一顶点u
(2.1)清空所有标记
(2.2)如果Find(u),继续
(2.3)否则,修改顶标集
(2.3.1)d=min{Ui+Vj-Wij},对于所有左侧被标记右侧未标记的边
(2.3.2)对于所有被标记的点,左侧的顶标-=d,右侧的顶标+=d
(2.3.3)回到(2.1)
(3)根据输出的匹配算出最大权

模板

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define INF 0x3f3f3f3f
using namespace std;

const int maxn=330;
int from[maxn],w[maxn][maxn];
int lx[maxn],ly[maxn],visx[maxn],visy[maxn],slack[maxn];
int nx,ny;
///定义slack[y]=min{lx[x]+ly[y]-w[x][y]},x已访问,y未访问

bool Find(int u)
{
    visx[u]=1;
    for(int v=0;v<ny;v++)if(!visy[v])
    {
        int tmp=lx[u]+ly[v]-w[u][v];
        if(tmp==0)
        {
            visy[v]=1;
            if(from[v]==-1 || Find(from[v]))
            {
                from[v]=u;
                return true;
            }
        }
        else slack[v]=min(slack[v],tmp);
    }
    return false;
}
int KM()
{
    for(int i=0;i<nx;i++)
    {
        ly[i]=0;
        lx[i]=-INF;
        for(int j=0;j<ny;j++)
            lx[i]=max(lx[i],w[i][j]);
    }
    memset(from,-1,sizeof(from));
    for(int u=0;u<nx;u++)
    {
        for(int i=0;i<ny;i++) slack[i]=INF;
        while(true)
        {
            memset(visx,0,sizeof(visx));
            memset(visy,0,sizeof(visy));
            if(Find(u)) break;
            int d=INF;
            for(int i=0;i<ny;i++)if(!visy[i])
                d=min(d,slack[i]);
            for(int i=0;i<nx;i++)if(visx[i])
                lx[i]-=d;
            for(int i=0;i<ny;i++)
            {
                if(visy[i]) ly[i]+=d;
                else slack[i]-=d;
            }
        }
    }
    int ans=0;
    for(int i=0;i<ny;i++)
        if(from[i]!=-1) ans+=w[from[i]][i];
    return ans;
}
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        nx=ny=n;
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                scanf("%d",&w[i][j]);
        printf("%d\n",KM());
    }
    return 0;
}

模板题

奔小康赚大钱 HDU-2255

查看评论

WordPress博客模板系统开发

-
  • 1970年01月01日 08:00

模板总结——二分图最大匹配

基本概念 二分图:二分图指的是这样的一种图,其所有顶点可以分成两个集合X和Y,其中X或Y中任意两个在同一个集合中的点都不相连,所有边关联在两个顶点集中。 匹配:匹配是图边集的一个子集,满足任意两条...
  • qq_37685156
  • qq_37685156
  • 2018-04-19 20:25:05
  • 8

uoj #80. 二分图最大权匹配 KM算法

题意 求二分图最大权匹配。 n 分析 妈妈我终于学会了KM算法系列。 一开始去网上找了个标,改了改交上去结果T了。。。然后就自己yy了一个模板出来。 具体的算法实现可以去看15年的论文...
  • qq_33229466
  • qq_33229466
  • 2018-01-19 15:47:24
  • 137

Tour(二分图最大权匹配)(网络流)

题意:给你一个有向图,边有权值,现在要你求若干个环包含所有的顶点,并且每个顶点只出现一次(除了一个环中的起始点)使得华中所有边得权值之和最小。 像这杨构成圈并且每个点只能属于一个圈的题, 可...
  • u014665013
  • u014665013
  • 2016-05-08 20:02:11
  • 1177

Kuhn-Munkres算法(二分图最大权匹配)

Kuhn-Munkres算法(二分图最大权匹配) 这篇博客没有题,就是简单的说一下KM算法,今天花了两个小时学KM算法,总算明白了基本套路和基本原理,但是,有一个点从头到尾我都没有懂,lx[i]+l...
  • bless924295
  • bless924295
  • 2016-11-15 16:22:04
  • 2885

二分图带权匹配问题

出处:http://www.byvoid.com/blog/match-km/#respond [二分图带权匹配与最佳匹配] 什么是二分图的带权匹配?二分图的带权匹配就是求出一个匹配集合,...
  • wsniyufang
  • wsniyufang
  • 2011-09-08 11:39:00
  • 6154

二分图最大权匹配 模板

/****************************************************** 二分图最佳匹配 (kuhn munkras 算法 O(m*m*n)). 邻接矩阵形式 。...
  • menguands
  • menguands
  • 2015-08-18 20:05:23
  • 192

费用流做二分图最大权匹配

费用流二分图最大权匹配的一个性质使用费用流计算二分图最大权匹配,考虑每次只增广一条最短路径(所以二分图上边权取负)。 我们会发现每次增广,二分图中匹配边边权总和会增加ΔL\Delta L 其中ΔL...
  • a710128
  • a710128
  • 2015-10-29 11:31:32
  • 781

求二分图最大权匹配的km算法

这个算法的本质还是不断的找增广路;KM算法是通过给每个顶点一个标号(叫做顶标)来把求最大权匹配的问题转化为求完备匹配的问的。设顶点Xi的顶标为A[i],顶点Yi的顶标为B[i],顶点Xi与Yj之间的边...
  • liguanxing
  • liguanxing
  • 2010-06-12 09:14:00
  • 1507

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

  • 2010年06月14日 21:50
  • 241KB
  • 下载
    个人资料
    持之以恒
    等级:
    访问量: 3308
    积分: 1172
    排名: 4万+
    文章存档