整理的算法模板合集: ACM模板


匈牙利算法又称为 KM 算法,可以在 O(n3)O(n^3)O(n3) 时间内求出二分图的 最大权完美匹配 。

考虑到二分图中两个集合中的点并不总是相同,为了能应用 KM 算法解决二分图的最大权匹配,需要先作如下处理:将两个集合中点数比较少的补点,使得两边点数相同,再将不存在的边权重设为 0,这种情况下,问题就转换成求最大权完美匹配问题 ,从而能应用 KM\tt KMKM 算法求解。

其实就是普通的匈牙利算法求二分图最大匹配的拓展版本

  • 顶标:两边点都有的标记(左 aia_iai​右 bjb_jbj​)满足 ai+bj≥wi,ja_i+b_j\ge w_{i,j}ai​+bj​≥wi,j​,不唯一。

  • 相等边:ai+bj=wi,ja_i+b_j=w_{i,j}ai​+bj​=wi,j​的边 (i,j)(i,j)(i,j)。

  • 相等子图:相等边构成的子图。

  • 交错树:增广路径形成的树。

  • KM\tt KMKM 算法核心定理 : 对于某组可行顶标,如果其相等子图存在完美匹配,那么,该匹配就是原二分图的最大权完美匹配。

具体流程:
(1) 分配可行顶标,并对每个节点执行 (2),(3),(4)。
(2) 匈牙利算法找增广。
(3) 找不到增广路(相等子图匹配)就调整顶标。
(4) 重复 (2),(3) 直到找到增广路。

模板题:P6577 【模板】二分图最大权完美匹配

O(n4)O(n^4)O(n4)的DFS\tt DFSDFS版本

/*有些小问题,别人的dfs都能拿50分我的只能拿10分...*/
typedef long long ll;
typedef unsigned long long ull;//卡精度
typedef pair<int,int> PII;const int N = 507, M = 5e3 +7, maxn = 1007;
const int mod = 1e9+7;
const ll INF = 1e15+7;ll w[N][N];//边权
ll la[N], lb[N];//左、右部点的顶标
bool va[N], vb[N];//访问标记,是否在交错树中
int match[N];//右部点匹配的左部点(一个只能匹配一个嘛)
int n;
ll delta, upd[N];bool dfs(int x)
{va[x] = 1;//标记访问:x在交错树中for(int y = 1; y <= n; ++ y){if(!vb[y]){//从左部点找右部点(如果不在交错树上)if(la[x] + lb[y] - w[x][y] == 0){//相等子图vb[y] = 1;//标记访问:y在交错树中if(!match[y] || dfs(match[y])){//匈牙利行为match[y] = x;return true;}}}else upd[y] = min(upd[y], la[x] + lb[y] - w[x][y]);//Δ}return false;
}ll KM()
{//左右部点各n个fill(la+1,la+n+1,-INF);//fill(lb+1,lb+n+1,0);for(int i = 1;i <= n; ++ i){for(int j = 1; j <= n; ++ j)//先分配左部点la[i] = max(la[i], w[i][j]);//取它能接触到的最大值以保证满足ai+bj>=wij}for(int i = 1; i <= n; ++ i){while(true){//直到该左部点找到匹配//memset(va, 0, sizeof va);//memset(vb, 0, sizeof vb);fill(va+1,va+n+1,0);fill(vb+1,vb+n+1,0);//for(int j = 1; j <= n; ++ j)//    upd[j] = INF;fill(upd+1,upd+n+1,INF);if(dfs(i)) break;//找到增广路了delta = INF;for(int j = 1; j <= n; ++ j)if(!vb[j])delta = min(delta, upd[j]);//找最小的Δfor(int j = 1; j <= n; ++ j){//修改顶标//把所有在交错树上的左右部点都左加右减 Δif(va[j])la[j] -= delta;if(vb[j])lb[j] += delta;}}}ll ans = 0;for(int i = 1; i <= n; ++ i)ans += w[match[i]][i];//答案加上所有完备匹配边的权值//注意二分图匹配是从左部点到右部点有权值//match数组存的是所有右部点匹配的左部点的编号//所以我们ans要加上w[match[i]][i]从左往右return ans;
}
int m;
int main()
{//memset(w, 0xcf, sizeof w);scanf("%d%d", &n, &m);for(int i = 1; i <= n; ++ i)for(int j = 1; j <= n; ++ j)w[i][j] = -INF;for(int i = 1 ;i <= m; ++ i){int x, y;ll z;scanf("%d%d%lld", &x, &y, &z);w[x][y] = max(w[x][y], z);//最大匹配嘛}printf("%lld\n", KM());for(int i = 1; i <= n; ++ i)printf("%d ", match[i]);puts("");return 0;
}

O(n3)O(n^3)O(n3)的BFS\tt BFSBFS迭代版本

把 DFS\tt DFSDFS 换成 BFS\tt BFSBFS。本质上没有什么区别
但是每个左边的点只会进队、搜索一次。
用p 数组记录的是增广交错树。

迭代版本的BFS\tt BFSBFS ,不需要 queue\tt queuequeue。

/*好难懂啊,还是抄板子吧*/
typedef long long ll;
typedef unsigned long long ull;//卡精度
typedef pair<int,int> PII;const int N = 507, M = 5e3 +7, maxn = 1007;
const int mod = 1e9+7;
const ll INF = 1e15+7;ll w[N][N];//边权
ll la[N], lb[N];//左、右部点的顶标
bool va[N], vb[N];//访问标记,是否在交错树中
int match[N];//右部点匹配的左部点(一个只能匹配一个嘛)
int n;
ll delta, upd[N];
int p[N];
ll c[N];void bfs(int x)
{int a, y = 0, y1 = 0;for(int i = 1; i <= n; ++ i)p[i] = 0, c[i] = INF;match[y] = x;do{a = match[y], delta = INF, vb[y] = true;for(int b = 1; b <= n; ++ b){if(!vb[b]){if(c[b] > la[a] + lb[b] - w[a][b])c[b] = la[a] + lb[b] - w[a][b], p[b] = y;if(c[b] < delta)//Δ还是取最小的delta = c[b], y1 = b;}}for(int b = 0; b <= n; ++ b)if(vb[b])la[match[b]] -= delta, lb[b] += delta;else c[b] -= delta;y = y1;}while(match[y]);while(y)match[y] = match[p[y]], y = p[y];
}ll KM()
{for(int i = 1; i <= n; ++ i)match[i] = la[i] = lb[i] = 0;for(int i = 1; i <= n; ++ i){for(int j = 1; j <= n; ++ j)vb[j] = false;bfs(i);}ll res = 0;for(int y = 1; y <= n; ++ y)res += w[match[y]][y];return res;
}int m;
int main()
{scanf("%d%d", &n, &m);for(int i = 1; i <= n; ++ i)for(int j = 1; j <= n; ++ j)w[i][j] = -INF;for(int i = 1 ;i <= m; ++ i){int x, y;ll z;scanf("%d%d%lld", &x, &y, &z);w[x][y] = max(w[x][y], z);//最大匹配嘛}printf("%lld\n", KM());for(int i = 1; i <= n; ++ i)printf("%d ", match[i]);puts("");return 0;
}

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

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

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

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

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

  3. 二分图的完全匹配---KM算法

    写在之前:更多二分图知识,请关注--->二分图知识导航篇 引述 KM算法全称Kuhn-Munkres,是一种求二分图完全.完美.最佳等匹配的方法,其实三个形容词都是指两个集内的所有顶点能够一一匹 ...

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

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

  5. HDU - 2255 奔小康赚大钱(二分图最大权匹配+KM)

    题目链接:点击查看 题目大意:中文题目,简单来说就是n个人和n个房子最大匹配,需要一一对应并且满足权值和最大 题目分析:二分图的完备匹配,条件完全符合KM算法的局限性,直接套模板即可,后续学习费用流( ...

  6. HDU 1853 HDU 3488【有向环最小权值覆盖问题 】带权二分图匹配 KM算法

    HDU 1853 & HDU 3488[有向环最小权值覆盖问题 ]最小费用最大流 In the kingdom of Henryy, there are N (2 <= N <= ...

  7. 奔小康赚大钱 HDU - 2255( 二分图匹配KM算法详解)

    题目 传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子.  这可是一件大事,关系到人民的住房问题啊.村里共有n间房间,刚好有n家老百姓,考虑到每家都要有房住(如果有老百 ...

  8. 训练指南 UVALive - 4043(二分图匹配 + KM算法)

    layout: post title: 训练指南 UVALive - 4043(二分图匹配 + KM算法) author: "luowentaoaa" catalog: true ...

  9. 【HDU 2255】奔小康赚大钱 (最佳二分匹配KM算法)

    奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Sub ...

最新文章

  1. 内核终端判断,微信?QQ?ipad?IE?移动?Google?opera……
  2. DHTML【11】--DOM
  3. Oracle数据库中dual是什么东西啊?
  4. Java权限管理系统源代码下载
  5. 苹果iOS设备解锁软件:iToolab UnlockGo
  6. JavaWeb框架三剑客前言
  7. 图像质量评价(IQA)综述
  8. 技嘉ide模式怎么改_bios如何设置为ide兼容模式_怎么进入bios把硬盘模式改成ide
  9. 峰值速率、系统容量、吞吐量、带宽之间的区别
  10. 对于目标检测中mAP@0.5的理解
  11. 企业抖音蓝V怎么认证?申请流程是怎样的?需要具备哪些条件?
  12. analy32.xll下载_Android Studio 4.0添加了Motion Editor和Build Analyzer
  13. 2018年高德地图POI全国数据下载
  14. 【公务员考试】结构化面试时间一般多长?
  15. x86、i386、IA-32、amd64、x64、x86-64、IA-64的区别
  16. 22考研清华905机械设计基础上岸经验分享
  17. 打工人必学的法律知识(三)——《中华人民共和国劳动争议调解仲裁法》
  18. CSS3系列视频教程,从入门到精通
  19. 动画指导在Excel中批量打印标签/送货单等等
  20. 视频、音频格式转换(以F4V转MP4为例)

热门文章

  1. Mask-RCNN论文解读
  2. 聊聊这两年学习slam啃过的书!
  3. 面试官(7): 聊一聊 Babel?
  4. 本地nginx多域名映射
  5. Hexo 个人博客 SEO 优化(3):改造你的博客,提升搜索引擎排名
  6. Acronis移动方案(四)
  7. TODO:macOS编译PHP7.1
  8. Java多线程并发常用类实例之:exchanger
  9. [C#反射]C#中的反射解析及使用.
  10. eds800变频器故障代码_变频器常见故障代码及处理实例(经典,建议收藏)