二分图的最佳完美匹配,也就是带权值的无向二分图中权值之和最大的完美匹配,整个图分为两个不相交的集合x和y,采用KM算法求解,也称匈牙利算法. 时间复杂度为O(n^3)

typedef int type;//实际数据类型,一般是int或doubleconst type inf = 2e9;
const double eps = 1e-8;
const int maxn = 330;int n, m;//x中结点个数,y中结点个数,下标从0开始
int matchx[maxn], matchy[maxn];//matchx[i]指的是xi匹配到的y中结点的编号,matchy[j]指的是yj匹配到的x中结点的编号
int visx[maxn], visy[maxn];//访问标记数组
type lx[maxn], ly[maxn];//x,y中每个点的期望值
type w[maxn][maxn];//类似邻接矩阵w[x][y]表示x到y有权值为w[x][y]的边
type slack[maxn];//y中每个元素的slack值bool dfs(int x) {visx[x] = 1;for (int y = 0; y < m; ++y) {if (visy[y]) continue;type tmp = lx[x] + ly[y] - w[x][y];if (tmp == 0) {//double的话改成: if (fabs(tmp)<=eps)visy[y] = 1;if (matchy[y] == -1 || dfs(matchy[y])) {matchx[x] = y;matchy[y] = x;return true;}}else {slack[y] = min(slack[y], tmp);}}return false;
}void KM() {memset(matchy, -1, sizeof(matchy));memset(ly, 0, sizeof(ly));for (int i = 0; i < n; ++i) {lx[i] = -inf;for (int j = 0; j < m; ++j) {lx[i] = max(lx[i], w[i][j]);}}for (int i = 0; i < n; ++i) {for (int j = 0; j < m; ++j) slack[j] = inf;while (1) {memset(visx, 0, sizeof(visx));memset(visy, 0, sizeof(visy));if (dfs(i)) break;type d = inf;for (int j = 0; j < m; ++j) {if (!visy[j]) d = min(d, slack[j]);}for (int j = 0; j < n; ++j) { if (visx[j]) lx[j] -= d; }for (int j = 0; j < m; ++j) {if (visy[j]) ly[j] += d;else slack[j] -= d;}}}
}

模板题 hdu2255 http://acm.hdu.edu.cn/showproblem.php?pid=2255

中文题目,裸的二分图最佳完美匹配问题

#include<bits/stdc++.h>
using namespace std;typedef int type;const type inf = 2e9;
const double eps = 1e-8;
const int maxn = 330;int n, m;
int matchx[maxn], matchy[maxn];
int visx[maxn], visy[maxn];
type lx[maxn], ly[maxn];
type w[maxn][maxn];
type slack[maxn];bool dfs(int x) {visx[x] = 1;for (int y = 0; y < m; ++y) {if (visy[y]) continue;type tmp = lx[x] + ly[y] - w[x][y];if (tmp == 0) {visy[y] = 1;if (matchy[y] == -1 || dfs(matchy[y])) {matchx[x] = y;matchy[y] = x;return true;}}else {slack[y] = min(slack[y], tmp);}}return false;
}void KM() {memset(matchy, -1, sizeof(matchy));memset(ly, 0, sizeof(ly));for (int i = 0; i < n; ++i) {lx[i] = -inf;for (int j = 0; j < m; ++j) {lx[i] = max(lx[i], w[i][j]);}}for (int i = 0; i < n; ++i) {for (int j = 0; j < m; ++j) slack[j] = inf;while (1) {memset(visx, 0, sizeof(visx));memset(visy, 0, sizeof(visy));if (dfs(i)) break;type d = inf;for (int j = 0; j < m; ++j) {if (!visy[j]) d = min(d, slack[j]);}for (int j = 0; j < n; ++j) { if (visx[j]) lx[j] -= d; }for (int j = 0; j < m; ++j) {if (visy[j]) ly[j] += d;else slack[j] -= d;}}}
}int main() {while (scanf("%d", &n) == 1) {m = n;for (int i = 0; i < n; ++i) {for (int j = 0; j < m; ++j) {scanf("%d", &w[i][j]);}}KM();int ans = 0;for (int i = 0; i < n; ++i) {ans += w[i][matchx[i]];}printf("%d\n", ans);}return 0;
}

转载于:https://www.cnblogs.com/wafish/p/10465361.html

二分图的最佳完美匹配(模板)相关推荐

  1. UVA - 1045 The Great Wall Game(二分图最佳完美匹配)

    题目大意:给出棋盘上的N个点的位置.如今问将这些点排成一行或者一列.或者对角线的最小移动步数(每一个点都仅仅能上下左右移动.一次移动一个) 解题思路:暴力+二分图最佳完美匹配 #include < ...

  2. UVa 11383 少林决胜(二分图最佳完美匹配)

    https://vjudge.net/problem/UVA-11383 题意: 给定一个N×N矩阵,每个格子里都有一个正整数W(i,j).你的任务是给每行确定一个整数row(i),每列也确定一个整数 ...

  3. 二分图最佳完美匹配——KM算法总结

    KM 算法 求解二分图最佳完美匹配的算法. 先来看一道例题Hdu 2255. 显然是KM的裸题.假设我们要匹配集合X和Y的点,先给每个点一个顶标Lx和Ly. 为什么要给顶标? 首先顶标是我们限制边的一 ...

  4. UVA 1349 Optimal Bus Route Design (二分图最小权完美匹配)

    恰好属于一个圈,那等价与每个点有唯一的前驱和后继,这让人想到了二分图, 把一个点拆开,点的前驱作为S集和点的后继作为T集,然后连边,跑二分图最小权完美匹配. 写的费用流..最大权完美匹配KM算法没看懂 ...

  5. 模板 - KM算法(O(n^3))(二分图最大权完美匹配)

    整理的算法模板合集: ACM模板 题目描述 给定一张二分图,左右部均有 n 个点,共有 m 条带权边,且保证有完美匹配. 求一种完美匹配的方案,使得最终匹配边的边权之和最大. //Data const ...

  6. 图论--二分图最佳完美匹配(KM模板)

    #include <iostream> #include <cstring> #include <cstdio>using namespace std; const ...

  7. 二分图最佳完美匹配——KM算法

    前情概要 学km算法之前,笔者还是希望大家已经掌握了匈牙利算法--也就是对于求解二分图最大匹配的算法.学习本算法的前提除了已经掌握C++语言之外,还需要掌握邻接表存图法,不会的朋友这里有传送门 [微笑 ...

  8. UVA1411 Ants(带权二分图的最大完美匹配、zkw费用流)

    题解 给定一些黑点白点,要求一个黑点链接一个白点并且线段不相交(转成二分图最大权匹配使用费用流解决)<训练指南>P351 输出方案:满流即为答案(满流是指这条路的流量跑满了,也就是说edg ...

  9. hdu-3488-Tour(KM最佳完美匹配)

    题意:有N个城市,M条街道,每条街道是单向的,现在要你设计多条路线覆盖所有的点,每条路线都是一个环,并且每个点仅能被一条路线覆盖且只经过一次(终始点除外) 分析:因为是有向圈,所以每个点的入度和出度应 ...

最新文章

  1. linux 启动网卡错误 RTNETLINK answers: File exists 解决方案
  2. Unity学习笔记 - Assets, Objects and Serialization
  3. Google Chrome等浏览器不允许关闭点击跟踪??
  4. No.1010_第七次团队会议
  5. C++ 大话数据结构 09: 中缀表达式 转后缀表达式 计算器
  6. python编程中的运算_Python编程中的四大运算法则
  7. 宝塔面板不能备份数据库,数据库备份大小20K,数据库备份报错mysqldump: Got error: 1045: Access denied for user 'root'@'localhost'
  8. js中采用词法作用域
  9. ubuntu 9.10学习笔记
  10. Johnson算法实现流水作业最优调度
  11. PS中和FW一样的精灵图缩小功能(像素栏输入数字就能缩小
  12. 自然语言处理seq2seq模型实现人工智能对对联(基于TensorFlow框架)
  13. 文本搜索引擎Lucene之filed详解和代码测试
  14. 利用Windows自带的计算器计算十六进制(八进制、二进制)数据
  15. 智能时代为什么需要区块链技术?
  16. FBX骨骼模型导入UE4
  17. Flutter 打包出错 报Gradle build failed to produce an .apk file. It’s likely that this file was generated
  18. crh寄存器_寄存器简写
  19. 清明时节,思念友人张锦文
  20. EVT、PVT、DVT

热门文章

  1. 【网址收藏】WIN10进入超级管理员账号(Administrator)
  2. Scala Iterator(迭代器)详解
  3. 【收藏】IntelliJ Idea中配置JavaFX Scene Builder
  4. Win10自带的邮件客户端配置腾讯企业邮箱账号
  5. Android Studio3.5.2离线安装gradle
  6. 为什么Java中只有值传递?
  7. mybatis修改mysql变量_Java通过MyBatis框架对MySQL数据进行增删查改的基本方法
  8. 黄金法则之《终身学习》
  9. 题库练习4(提取不重复的数字、字符个数统计、数字颠倒、字符串反转)
  10. mysql8.0.20忘记密码_mysql8.0.19忘记密码的完美解决方法