1 问题描述
何为二分图的最大权匹配问题?

最大权二分匹配问题就是给二分图的每条边一个权值,选择若干不相交的边,得到的总权值最大。

2 解决方案

解决这个问题可以用KM算法。理解KM算法需要首先理解“可行顶标”的概念。可行顶标是指关于二分图两边的每个点的一个值lx[i]或ly[j],保证对于每条边w[i][j]都有lx[i]+ly[j]-w[i][j]>=0。如果所有满足lx[i]+ly[j]==w[i][j]的边组成的导出子图中存在一个完美匹配,那么这个完美匹配肯定就是原图中的最大权匹配。理由很简单:这个匹配的权值之和恰等于所有顶标的和,由于上面的那个不等式,另外的任何匹配方案的权值和都不会大于所有顶标的和。

但问题是,对于当前的顶标的导出子图并不一定存在完美匹配。这时,可以用某种方法对顶标进行调整。调整的方法是:根据最后一次不成功的寻找交错路的DFS,取所有i被访问到而j没被访问到的边(i,j)的lx[i]+ly[j]-w[i][j]的最小值d。将交错树中的所有左端点的顶标减小d,右端点的顶标增加d。经过这样的调整以后:原本在导出子图里面的边,两边的顶标都变了,不等式的等号仍然成立,仍然在导出子图里面;原本不在导出子图里面的边,它的左端点的顶标减小了,右端点的顶标没有变,而且由于d的定义,不等式仍然成立,所以他就可能进入了导出子图里。

初始时随便指定一个可行顶标,比如说lx[i]=max{w[i][j]|j是右边的点},ly[i]=0。然后对每个顶点进行类似Hungary算法的find过程,如果某次find没有成功,则按照这次find访问到的点对可行顶标进行上述调整。这样就可以逐步找到完美匹配了。

值得注意的一点是,按照上述d的定义去求d的话需要O(N2)的时间,因为d需要被求O(N2)次,这就成了算法的瓶颈。可以这样优化:设slack[j]表示右边的点j的所有不在导出子图的边对应的lx[i]+ly[j]-w[i][j]的最小值,在find过程中,若某条边不在导出子图中就用它对相应的slack值进行更新。然后求d只要用O(N)的时间找到slack中的最小值就可以了。

下面代码所使用的测试数据如下图:

package com.liuzhen.practice;import java.util.Scanner;public class Main {public static int MAX = 100;public static int n;public static int[][] value = new int[MAX][MAX];   //给定二分图的权重值public static int[] lx = new int[MAX];   //记录二分图左半部分顶点的可行顶标public static int[] ly = new int[MAX];   //记录二分图右半部分顶点的可行顶标public static boolean[] sx = new boolean[MAX];//用于记录二分图左半部分顶点是否在最终结果中public static boolean[] sy = new boolean[MAX];//用于记录二分图右半部分顶点是否在最终结果中public static int[] pre = new int[MAX];  //用于记录最终结果中顶点y匹配的顶点xpublic boolean dfs(int x) {   //采用匈牙利算法找增广路径sx[x] = true;       //代表左半部分顶点x包含在最终结果中for(int y = 0;y < n;y++) {if(!sy[y] && lx[x] + ly[y] == value[x][y]) {sy[y] = true;   //代表右半部分顶点y包含在最终结果中if(pre[y] == -1 || dfs(pre[y])) {pre[y] = x;return true;}}}return false;}public int getKM(int judge) {if(judge == -1) {  //代表寻找二分图的最小权匹配for(int i = 0;i < n;i++)for(int j = 0;j < n;j++)value[i][j] = -1 * value[i][j];  //把权值变为相反数,相当于找最大权匹配}//初始化lx[i]和ly[i]for(int i = 0;i < n;i++) {ly[i] = 0;lx[i] = Integer.MIN_VALUE;for(int j = 0;j < n;j++) {if(value[i][j] > lx[i])lx[i] = value[i][j];}}for(int i = 0;i < n;i++)pre[i] = -1;      //初始化右半部分顶点y的匹配顶点为-1for(int x = 0;x < n;x++) { //从左半部分顶点开始,寻找二分图完美匹配的相等子图完美匹配while(true) {for(int i = 0;i < n;i++) {//每次寻找x的增广路径,初始化sx[i]和sy[i]均为被遍历sx[i] = false;sy[i] = false;}if(dfs(x))  //找到从x出发的增广路径,结束循环,寻找下一个x的增广路径break;//下面对于没有找到顶点x的增广路径进行lx[i]和ly[i]值的调整int min = Integer.MAX_VALUE;for(int i = 0;i < n;i++) {if(sx[i]) {  //当sx[i]已被遍历时for(int j = 0;j < n;j++) {if(!sy[j]) {  //当sy[j]未被遍历时if(lx[i] + ly[j] - value[i][j] < min)min = lx[i] + ly[j] - value[i][j];}}}}if(min == 0)return -1;for(int i = 0;i < n;i++) {if(sx[i])lx[i] = lx[i] - min;if(sy[i])ly[i] = ly[i] + min;}}}int sum = 0;for(int y = 0;y < n;y++) {System.out.println("y顶点"+y+"和x顶点"+pre[y]+"匹配");if(pre[y] != -1)sum = sum + value[pre[y]][y];}if(judge == -1)sum = -1 * sum;return sum;}public static void main(String[] args) {Main test = new Main();Scanner in = new Scanner(System.in);n = in.nextInt();int k = in.nextInt();   //给定二分图的有向边数目for(int i = 0;i < k;i++) {int x = in.nextInt();int y = in.nextInt();int v = in.nextInt();value[x][y] = v;}System.out.println(test.getKM(1));}
}

运行结果:

10
0 2
1 3
0 2
0 4
2 2
2 1
3 3
4 2
3 8
4 3
y顶点0和x顶点2匹配
y顶点1和x顶点0匹配
y顶点2和x顶点1匹配
y顶点3和x顶点4匹配
y顶点4和x顶点3匹配

Java实现二分图的最大权匹配相关推荐

  1. hdu 2853Assignment (二分图的最大权匹配)

    //hdu2853 //二分图的最大权匹配,图中有一些边,在等权值的条件下有优先选择权. //因为是选n个进行匹配,我们将每条边的权值扩大(n+1)倍,这样每条边相对大小是一样的 //对于有优先选择权 ...

  2. java 二分图带权匹配_算法笔记_139:二分图的最大权匹配(Java)

    packagecom.liuzhen.practice;importjava.util.Scanner;public classMain {public static int MAX = 100;pu ...

  3. POJ 2195 Going Home 二分图的最大权匹配

    POJ2195 Going Home 最小费用最大流 Going Home Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2 ...

  4. hdu 3395(费用流,二分图的最大权匹配)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3395 解题思路: 这个构图很容易出错,最开始都容易想,把每个点拆开,分为攻击和被攻击的,建图如下: 源 ...

  5. 【算法笔记】二分图最大权匹配 - KM算法(dfs版O(n4) + bfs版O(n3))

    整理的算法模板合集: ACM模板 匈牙利算法又称为 KM 算法,可以在 O(n3)O(n^3)O(n3) 时间内求出二分图的 最大权完美匹配 . 考虑到二分图中两个集合中的点并不总是相同,为了能应用 ...

  6. 二分图最大权匹配 KM算法

    KM算法的正确性基于以下定理: 若由二分图中所有满足A[i]+B[i]=w[i][j]的边C(i,j)构成的子图(即相等子图)有完备匹配,那么这个完备匹配就是二分图的最大权匹配 基本概念 1.完备匹配 ...

  7. 二分图最大权匹配问题KM算法讲解 HDU 2255 奔小康赚大钱

    作者:logosG 链接:https://www.cnblogs.com/logosG/p/logos.html (讲解的KM算法,特别厉害!!!) KM算法: 现在我们来考虑另外一个问题:如果每个员 ...

  8. 二分图最大匹配及最大权匹配

    二分图最大匹配学习 一.二分图的基本知识 二.二分图最大匹配 什么是二分图最大匹配 怎么求二分图最大匹配 三.二分图最大权匹配 四.例题训练 三.最小点覆盖数 一位大佬的神级解释 本以为有了网络流,就 ...

  9. Java实现二分图的最大匹配

    1 问题描述 何为二分图的最大匹配问题? 引用自百度百科: 首先得说明一下何为匹配: 给定一个二分图G,在G的一个子图M中,M的边集{E}中的任意两条边都不依附于同一个顶点,则称M是一个匹配. 极大匹 ...

最新文章

  1. R语言使用fs包的file_copy函数、dir_copy函数、link_copy函数将文件、目录、超链接从一个位置拷贝(copy)到另一个位置
  2. pandas 2 选择数据
  3. 《毅力–如何培养自律的习惯》读书笔记
  4. 常用来进行钢结构节点输出的软件是什么_高效办公神器!350个计算表格+30个小软件,工程算量不犯难...
  5. 常用的lucene分词器-笔记
  6. 有oracle操作系统,Oracle操作系统认证方式
  7. android finish后不能ondestroy_Android面试基础(一)
  8. 开发申请评分卡的第一步要做什么
  9. Salesforce删除数据时出现Insufficient privileges的可能原因
  10. 论文查重算法 python_论文查重降重绝密方法
  11. FGSM实例:利用fgsm攻击RMB识别模型
  12. 转载--多核DSP快速入门
  13. 简单FTP服务器搭建教程
  14. 探索者易打软件--实现AutoCAD批量打印和自动命名
  15. 基于 Verilog 的经典数字电路设计(10)三态门
  16. 基于hyperleger fabric区块链的校园化妆品交易平台搭建
  17. JN项目-qq昵称含有表情无法进行第三方登录
  18. RPL(8):RFC6550翻译(8)---下行路由
  19. 全国企业信用信息公示系统
  20. 小虎电商浏览器:拼多多怎么看单品实时数据

热门文章

  1. php手机短信接口发送验证码,PHP手机短信接口发送验证码
  2. dfp方法例题_最优化之DFP算法考试题
  3. Cloud Functions
  4. 支付系统账务相关的一些知识
  5. 皮带秤 算法_双通道电子皮带秤速度新算法的研究.pdf
  6. leetcode 151 Reverse Words in a String (python)
  7. mysql8 新特性总结
  8. 网民隐私被窃取成牟利工具
  9. 【案例精选】聚铭网络流量智能分析审计系统助力六安市司法局推进网络安全防护建设
  10. Java零基础入门:实战教程(二)