二分图带权匹配

  带权匹配是指在最大匹配的基础上,使匹配边的边权和最大。一般有两种写法,一个是KM算法(只针对可以完备匹配的二分图),一个是费用流。

  KM算法在稠密图上比费用流更优秀一些,不过应用范围太小,所以还是鼓励大家用费用流。当然啦,作为一种算法KM也是我们需要了解的(况且我不会网络流??)。

  KM算法有个流程:

  1、存图

  2、用贪心算法初始化标杆

  3、运用匈牙利算法找到完备匹配

  4、如果找不到完备匹配,通过修改标杆增加一些边

  5、重复做3和4两个步骤,直到找到完备匹配。

  其他的话,我表述的也不是很好,理解有限抱歉。有一篇很好的博客,推荐一下:http://www.cnblogs.com/Lanly/p/6291214.html

#include<bits/stdc++.h>
using namespace std;
const int N=105;
int n,ans,delta,w[N][N],match[N],la[N],lb[N],va[N],vb[N];
bool dfs(int x){
    va[x]=1;
    for(int y=1;y<=n;++y){
        if(!vb[y]){
            if(va[x]+vb[y]-w[x][y]==0){
                vb[y]=1;
                if(!match[y]||dfs(match[y])){
                    match[y]=x;
                    return true;
                }
            }else delta=min(delta,la[x]+lb[y]-w[x][y]);
        }
    }
    return false;
}
int KM(){
    for(int i=1;i<=n;++i){
        la[i]=-(1<<30);
        lb[i]=0;
        for(int j=1;j<=n;++j) la[i]=max(la[i],w[i][j]);
    }
    for(int i=1;i<=n;++i){
        while(true){
            memset(va,0,sizeof(va));
            memset(vb,0,sizeof(vb));
            delta=1<<30;
            if(dfs(i)) break;
            for(int j=1;j<=n;++j){
                if(va[j]) la[j]-=delta;
                if(vb[j]) lb[j]-=delta;
            }
        }
    }
    ans=0;
    for(int i=1;i<=n;++i) ans+=w[match[i]][i];
    return ans;
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
    for(int j=1;j<=n;++j) scanf("%d",&w[i][j]);
    printf("%d\n",KM());
    return 0;
}

原文地址:https://www.cnblogs.com/kgxw0430/p/10221972.html

时间: 2024-11-05 18:42:31

二分图带权匹配的相关文章

hdu 2255 二分图带权匹配 模板题

模板+注解在 http://blog.csdn.net/u011026968/article/details/38276945 hdu 2255 代码: //KM×î´ó×îСƥÅä #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> using namespace std; #define INF 0x0fffffff const int MAXN

二分图带权匹配(推箱子问题的思考)

转载请附上原文链接: http://blog.csdn.net/u013351484/article/details/51598270 二分图带权匹配(也叫二分图最优(最佳)匹配,Kuhn-Munkres 算法) 预备知识:二分图最大匹配,二分图完备(完美)匹配 二分图带权匹配,可以把它看作集合 X 的每个顶点到集合 Y 的每个顶点均有边的二分图(设权重均为正数,则原来分别在集合 X 与集合 Y 中没边的顶点 xi,yi 就可以添加一条权重为 0 的边,即 w[xi,yi] = 0):这样的二分

poj 2195 二分图带权匹配

题意:有一个矩阵,某些格有人,某些格有房子,每个人可以上下左右移动,问给每个人进一个房子,所有人需要走的距离之和最小是多少. 貌似以前见过很多这样类似的题,都不会,现在知道是用KM算法做了 KM算法目前还没弄懂,先套模板做 Sample Input 2 2 .m H. 5 5 HH..m ..... ..... ..... mm..H 7 8 ...H.... ...H.... ...H.... mmmHmmmm ...H.... ...H.... ...H.... 0 0 Sample Out

二分图带权匹配-Kuhn-Munkres算法模板 [二分图带权匹配]

尴尬...理解不太好T T 1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 #define inf 0x3f3f3f3f 7 8 const int maxn=1005; 9 10 int n; 11 //标杆序号 12 int lx[maxn],ly[maxn]; 13 //是否被搜索过 14

Ants 二分图带权最小匹配

Ants Solution: 此题最重要的是转化题意! 直接上图(图中红色才是正确方案): 这是一种很简单的情况,但是却告诉了我们很重要的信息. 仔细观察,可以发现,似乎最优方案的两两间连的边,距离值和最小! 那么,找一组连边方案,使得两两距离值和最小必然是最优方案. 为什么会这样呢, 其实是因为只要有相交的边,就会构成类似上图的'X'型, 那么就必定会存在两个三角形,相交的边一起构成两个三角形中的两边,必然大于其对应的第三边! 因而,我们只要选则第三边,就能保证不交,与此同时,选出来的边距离值

KM——二分图带权最大匹配

定义:完备匹配:两个集合顶点数都为N,且有N条边被匹配<每个点都匹配>.形象地理解:有n男n女,每个人都可以找到自己心仪的对象. 特点:只适用于完备匹配(两个集合顶点数都为N,且有N条边被匹配<每个点都匹配>) 定义: · 设二分图两个顶点集合为{A},{B} · 顶标:给每个顶点赋值,全称顶点标记值 设集合{A}顶标为la[i],{B}顶标为lb[i],满足对于任何一条边W,两个顶点的顶标和>=边的权值(la[i] + lb[j] >= W(i , j) ) · 交错

hdu 1569 &amp;1565 (二分图带权最大独立集 - 最小割应用)

要选出一些点,这些点之间没有相邻边且要求权值之和最大,求这个权值 分析:二分图带权最大独立集. 用最大流最小割定理求解.其建图思路是:将所有格点编号,奇数视作X部,偶数视作Y部,建立源点S和汇点T, S向X部的点建边,Y部向T建边,容量为该点权值. 相邻的一对点(肯定是一奇一偶),由X中的点向Y中的点建边,容量为正无穷. 最后跑出最大流,|带权最大独立集| = |点权之和| - |最小割| = |点权之和| - |最大流| #include<iostream> #include<cstr

poj2195 bfs+最小权匹配

题意:给个矩阵,矩阵里有一些人和房子(人数和房子数相等),一个人只进一个房子(可以路过房子而不进),每走一步花费1美金,求所有人都进入房子的最小花费,这是典型的二分图带权匹配问题. 这题就是建图有点麻烦,但绝不抽象,直接用BFS遍历每个人到所有房子的距离,遍历出一个就拉一条人到房子有向边,建完图就是套模板了. 注意:KM算法是求最大权匹配的,要求最小权就要把所有边取相反数,最后结果再取相反数,但这只能是完美匹配,不完美匹配还要变一些. 1 #include<cstdio> 2 #include

POJ 3686 The Windy&#39;s【最小权匹配(神建图啊)】

大意:有n个任务m个机器,告诉你n*m的矩阵表示每个任务在每个机器上完成需要的时间 问所有任务完成的总时间最少?(比如第一个任务在第一分钟完成第二个任务在第二分钟完成   则总时间为1 + 2 = 3 分析: 该题自己做的时候没有思路 后来在网上搜题解,感觉建图真是太厉害了 假设最优情况下,个个任务需要的时间分别为a1, a2, a3, ……,an 那么总时间t = n * a1 + (n - 1) * a2 + ……+ 2 * an - 1 + an 也就是说只需要考虑系数就可以了 我们先假设