二分图的最佳完美匹配(模板)
二分图的最佳完美匹配,也就是带权值的无向二分图中权值之和最大的完美匹配,整个图分为两个不相交的集合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
二分图的最佳完美匹配(模板)相关推荐
- UVA - 1045 The Great Wall Game(二分图最佳完美匹配)
题目大意:给出棋盘上的N个点的位置.如今问将这些点排成一行或者一列.或者对角线的最小移动步数(每一个点都仅仅能上下左右移动.一次移动一个) 解题思路:暴力+二分图最佳完美匹配 #include < ...
- UVa 11383 少林决胜(二分图最佳完美匹配)
https://vjudge.net/problem/UVA-11383 题意: 给定一个N×N矩阵,每个格子里都有一个正整数W(i,j).你的任务是给每行确定一个整数row(i),每列也确定一个整数 ...
- 二分图最佳完美匹配——KM算法总结
KM 算法 求解二分图最佳完美匹配的算法. 先来看一道例题Hdu 2255. 显然是KM的裸题.假设我们要匹配集合X和Y的点,先给每个点一个顶标Lx和Ly. 为什么要给顶标? 首先顶标是我们限制边的一 ...
- UVA 1349 Optimal Bus Route Design (二分图最小权完美匹配)
恰好属于一个圈,那等价与每个点有唯一的前驱和后继,这让人想到了二分图, 把一个点拆开,点的前驱作为S集和点的后继作为T集,然后连边,跑二分图最小权完美匹配. 写的费用流..最大权完美匹配KM算法没看懂 ...
- 模板 - KM算法(O(n^3))(二分图最大权完美匹配)
整理的算法模板合集: ACM模板 题目描述 给定一张二分图,左右部均有 n 个点,共有 m 条带权边,且保证有完美匹配. 求一种完美匹配的方案,使得最终匹配边的边权之和最大. //Data const ...
- 图论--二分图最佳完美匹配(KM模板)
#include <iostream> #include <cstring> #include <cstdio>using namespace std; const ...
- 二分图最佳完美匹配——KM算法
前情概要 学km算法之前,笔者还是希望大家已经掌握了匈牙利算法--也就是对于求解二分图最大匹配的算法.学习本算法的前提除了已经掌握C++语言之外,还需要掌握邻接表存图法,不会的朋友这里有传送门 [微笑 ...
- UVA1411 Ants(带权二分图的最大完美匹配、zkw费用流)
题解 给定一些黑点白点,要求一个黑点链接一个白点并且线段不相交(转成二分图最大权匹配使用费用流解决)<训练指南>P351 输出方案:满流即为答案(满流是指这条路的流量跑满了,也就是说edg ...
- hdu-3488-Tour(KM最佳完美匹配)
题意:有N个城市,M条街道,每条街道是单向的,现在要你设计多条路线覆盖所有的点,每条路线都是一个环,并且每个点仅能被一条路线覆盖且只经过一次(终始点除外) 分析:因为是有向圈,所以每个点的入度和出度应 ...
最新文章
- linux 启动网卡错误 RTNETLINK answers: File exists 解决方案
- Unity学习笔记 - Assets, Objects and Serialization
- Google Chrome等浏览器不允许关闭点击跟踪??
- No.1010_第七次团队会议
- C++ 大话数据结构 09: 中缀表达式 转后缀表达式 计算器
- python编程中的运算_Python编程中的四大运算法则
- 宝塔面板不能备份数据库,数据库备份大小20K,数据库备份报错mysqldump: Got error: 1045: Access denied for user 'root'@'localhost'
- js中采用词法作用域
- ubuntu 9.10学习笔记
- Johnson算法实现流水作业最优调度
- PS中和FW一样的精灵图缩小功能(像素栏输入数字就能缩小
- 自然语言处理seq2seq模型实现人工智能对对联(基于TensorFlow框架)
- 文本搜索引擎Lucene之filed详解和代码测试
- 利用Windows自带的计算器计算十六进制(八进制、二进制)数据
- 智能时代为什么需要区块链技术?
- FBX骨骼模型导入UE4
- Flutter 打包出错 报Gradle build failed to produce an .apk file. It’s likely that this file was generated
- crh寄存器_寄存器简写
- 清明时节,思念友人张锦文
- EVT、PVT、DVT
热门文章
- 【网址收藏】WIN10进入超级管理员账号(Administrator)
- Scala Iterator(迭代器)详解
- 【收藏】IntelliJ Idea中配置JavaFX Scene Builder
- Win10自带的邮件客户端配置腾讯企业邮箱账号
- Android Studio3.5.2离线安装gradle
- 为什么Java中只有值传递?
- mybatis修改mysql变量_Java通过MyBatis框架对MySQL数据进行增删查改的基本方法
- 黄金法则之《终身学习》
- 题库练习4(提取不重复的数字、字符个数统计、数字颠倒、字符串反转)
- mysql8.0.20忘记密码_mysql8.0.19忘记密码的完美解决方法