hdu2255 奔小康赚大钱,最大权匹配,KM算法
最大权匹配
KM算法
算法步骤:
设顶点Xi的顶标为a[i],顶点Yi的顶标为b[i]
ⅰ.初始时。a[i]为与Xi相关联的边的最大权值。b[j]=0。保证a[i]+b[j]>=w(i,j)成立
ⅱ.当相等子图中不包括完备匹配时,就适当改动顶标以扩大相等子图,直到找到完备匹配为止
ⅲ.改动顶标的方法
当从Xi寻找交错路失败后,得到一棵交错树,它的全部叶子节点都是X节点。对交错树中X顶点的顶标降低d值,Y顶点的顶标添加d值,对于图中全部的边(i,j),
能够看到:
i和j都不在交错树中,边(i,j)仍然不属于相等子图
i和j都在交错树中,边(i,j)仍然属于相等子图
i不在交错树中。j在交错树中,a[i]+b[j]扩大。边(i,j)不属于相等子图
i在交错树,j不在交错树中,边(i,j)有可能增加到相等子图中
为了使a[i]+b[j]>=w(i,j)始终成立,且至少有一条边增加到相等子图中,d=min{a[i]+b[j]-w(i,j)},i在交错树中,j不在交错树中
时间复杂度:须要找O(n)次增广路。每次增广最多须要改动O(n)次顶标。每次改动顶标时枚举边来求d值,复杂度为O(n2),总的复杂度为O(n4).简单优化能够减少到O(n3),每一个Y顶点一个“松弛量”函数slack,每次開始找增广路时初始化为无穷大。
在寻找增广路的过程中,检查边(i,j)时。假设不在相等子图中,则让slack[j]变成原值与A[i]+B[j]-w[i,j]的较小值。这样。在改动顶标时,取全部不在交错树中的Y顶点的slack值中的最小值作为d值就可以。但还要注意一点:改动顶标后,要把全部的slack值都减去d。
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#define for0(a,b) for(a=0;a<b;++a)
#define for1(a,b) for(a=1;a<=b;++a)
#define foru(i,a,b) for(i=a;i<=b;++i)
#define ford(i,a,b) for(i=a;i>=b;--i)
using namespace std;
typedef long long ll;
const int maxn = 310;
const int INF = 1e9;
/*KM算法
*O(nx*nx*ny)
*求最大权匹配
*若求最小权匹配,可将权值取相反数,结果再取相反数。
*/
int nx, ny;
int g[maxn][maxn];
int linker[maxn], lx[maxn], ly[maxn];//y中各点匹配状态,x,y中的顶标
int slack[maxn];
bool visx[maxn], visy[maxn]; bool DFS(int x)
{
visx[x] = true;
for(int y=0; y<ny; ++y){
if(visy[y]) continue;
int tmp = lx[x] + ly[y] - g[x][y];
if(tmp == 0){
visy[y] = true;
if(linker[y] == -1 || DFS(linker[y])){
linker[y] = x;
return true;
}
}
else if(slack[y]> tmp)
slack[y] = tmp;
}
return false;
} int KM()
{
memset(linker, -1, sizeof linker );
memset(ly, 0, sizeof ly );
for(int i=0; i<nx; ++i){
lx[i] = - INF;
for(int j=0; j<ny; ++j)
if(g[i][j]> lx[i])
lx[i] = g[i][j];
}
for(int x=0; x<nx; ++x)
{
for(int i=0; i<ny; ++i)
slack[i] = INF;
while(true)
{
memset(visx, false, sizeof visx );
memset(visy, false, sizeof visy );
if(DFS(x)) break;
int d = INF;
for(int i=0; i<ny; ++i)
if(!visy[i] && d>slack[i])
d = slack[i];
for(int i=0; i<nx; ++i)
if(visx[i])
lx[i] -= d;
for(int i=0; i<ny; ++i)
{
if(visy[i]) ly[i] += d;
else slack[i] -= d;
}
}
}
int res = 0;
for(int i=0; i<ny; ++i)
if(linker[i] != -1)
res += g[linker[i]][i];
return res;
} //HDU 2255
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.cpp","r",stdin);
freopen("out.cpp", "w", stdout);
#endif // ONLINE_JUDGE
int n;
while(~scanf("%d", &n))
{
for(int i=0; i<n; ++i)
for(int j=0; j<n; ++j)
scanf("%d", &g[i][j]);
nx = ny = n;
printf("%d\n" ,KM());
}
return 0;
}
hdu2255 奔小康赚大钱,最大权匹配,KM算法的更多相关文章
- hdu2255 奔小康赚大钱 二分图最佳匹配--KM算法
传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子.这可是一件大事,关系到人民的住房问题啊.村里共有n间房间,刚好有n家老百姓,考虑到每家都要有房住(如果有老百姓没房子住 ...
- 【HDU 2255】奔小康赚大钱 (最佳二分匹配KM算法)
奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Subm ...
- hdu 2255 奔小康赚大钱 最大权匹配KM
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2255 传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子.这可是一件大事 ...
- hdu-2255.奔小康赚大钱(最大权二分匹配)
奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Subm ...
- HDU2255 奔小康赚大钱 (最大权完美匹配) 模板题【KM算法】
<题目链接> 奔小康赚大钱 Problem Description 传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子.这可是一件大事,关系到人民的住房问题啊 ...
- HDU 2255.奔小康赚大钱 最大权匹配
奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Subm ...
- hdu2255 奔小康赚大钱 km算法解决最优匹配(最大权完美匹配)
/** 题目:hdu2255 奔小康赚大钱 km算法 链接:http://acm.hdu.edu.cn/showproblem.php?pid=2255 题意:lv 思路:最优匹配(最大权完美匹配) ...
- Hdu2255 奔小康赚大钱(二分图最大权匹配KM算法)
奔小康赚大钱 Problem Description 传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子. 这可是一件大事,关系到人民的住房问题啊.村里共有n间房间,刚好 ...
- HDU2255 奔小康赚大钱 —— 二分图最大权匹配 KM算法
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2255 奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others) ...
随机推荐
- myeclipse启动错误:org.eclipse.swt.SWTError: No more handles
myeclipse启动错误,生成日志: !SESSION 2014-11-06 09:13:16.296 ----------------------------------------------- ...
- #ECMASCRIPT6笔记
ECMASCRIPT6笔记 来源于http://es6.ruanyifeng.com/#docs/proxy 是我在阅读时做下的笔记,方便以后查阅 Symbol ES5 的对象属性名都是字符串,这容易 ...
- [转] webpack3.0踩坑:postcss-loader的使用
解决方案: 只是换了一种引入方式,解决了 1,创建postcss.config.js文件,添加如下代码:(引入autoprefixer插件) 1 2 3 4 module.exports = { ...
- UOJ Round #1 题解
题解: 质量不错的一套题目啊..(题解也很不错啊) t1: 首先暴力显然有20分,把ai相同的缩在一起就有40分了 然后会发现由于原来的式子有个%很不方便处理 so计数题嘛 考虑一下容斥 最终步数=初 ...
- 6-14 Abbott的复仇 uva816
我的第一题bfs 将方向固定 NESW 然后左转和右转就是+3和+1!!! 还有就是 建立一个数组 储存父节点 这样就可以往回打印出路径 打印的截至条件是 d[][][]==0时 说明到 ...
- 深入理解类成员函数的调用规则(理解成员函数的内存为什么不会反映在sizeof运算符上、类的静态绑定与动态绑定、虚函数表)
本文转载自:http://blog.51cto.com/9291927/2148695 总结: 一.成员函数的内存为什么不会反映在sizeof运算符上? 成员函数可以被看作是类 ...
- php字符串截取
保留字符串前面的 substr($str,start[,$length]); start 为负数 则从后面开始截取 leng为负数则返回的字符串将从 $str 结尾处向前数第 start 个字符开始 ...
- hdu 3466 Proud Merchants 【限制性01背包】+【贪心】
题目链接:https://vjudge.net/contest/103424#problem/J 转载于:https://www.bbsmax.com/A/RnJW16GRdq/ 题目大意: 有n个商 ...
- HDU 1711Number Sequence【KMP模板题】
<题目链接> 题目大意: 意思是给出两个串,找出匹配串在模式串中的位置. 解题分析: KMP算法模板题. #include <cstdio> #include <cstr ...
- <<c专家编程>>笔记
C专家编程摘录 c操作符的优先级 有时一些c操作符有时并不会像你想象的那样工作. 下方表格将说明这个问题: 优先级问题 表达式 期望的情况 实际情况 . 优先级高于* *p.f (*p).f *(p. ...