【HDOJ 2255】奔小康赚大钱(KM算法)
奔小康赚大钱
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 6051 Accepted Submission(s): 2667
这但是一件大事,关系到人民的住房问题啊。
村里共同拥有n间房间,刚好有n家老百姓,考虑到每家都要有房住(假设有老百姓没房子住的话,easy引起不安定因素),每家必须分配到一间房子且仅仅能得到一间房子。
还有一方面,村长和另外的村领导希望得到最大的效益,这样村里的机构才会有钱.因为老百姓都比較富裕,他们都能对每一间房子在他们的经济范围内出一定的价格,比方有3间房子,一家老百姓能够对第一间出10万,对第2间出2万,对第3间出20万.(当然是在他们的经济范围内).如今这个问题就是村领导如何分配房子才干使收入最大.(村民即使有钱购买一间房子但不一定能买到,要看村领导分配的).
2
100 10
15 23
123
pid=3360" target="_blank">3360
1083 1281pid=1533" target="_blank">1533
2426第一次接触KM算法,在学这个算法前最好先学二分匹配。算是二分图最大匹配的一个演变——带权匹配
网上讲KM的文章也不少,贴两个我学习看的帖子
http://philoscience.iteye.com/blog/1754498
http://blog.sina.com.cn/s/blog_691ce2b701016reh.html
我感觉第一个比較有助于理解,但代码实现是JAVA来写的。第二个能够学学详细写法,当然不是全然固定的,仅供參考。
这题就是个裸题,建个图跑遍KM即可。
代码例如以下:
#include <iostream>
#include <cmath>
#include <vector>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
#include <list>
#include <algorithm>
#include <map>
#include <set>
#define LL long long
#define fread() freopen("in.in","r",stdin)
#define fwrite() freopen("out.out","w",stdout) using namespace std;
const int INF = 0x3f3f3f3f;
const int msz = 10000;
const double eps = 1e-8; //存图
int mp[333][333];
// x顶标 y顶标
int lx[333],ly[333],link[333],slack[333];
bool visx[333],visy[333];
int n; bool cal(int x)
{
visx[x] = 1;
for(int y = 0; y < n; ++y)
{
if(visy[y]) continue; int tmp = lx[x]+ly[y]-mp[x][y];
//边在二分匹配中
if(tmp == 0)
{
visy[y] = 1;
if(link[y] == -1 || cal(link[y]))
{
link[y] = x;
return 1;
}
}
//边不在二分匹配中
else slack[y] = min(slack[y],tmp);
}
return false;
} int KM()
{
memset(ly,0,sizeof(ly));
memset(link,-1,sizeof(link)); for(int i = 0; i < n; ++i)
{
memset(slack,INF,sizeof(slack));
while(1)
{
memset(visx,0,sizeof(visx));
memset(visy,0,sizeof(visy)); //xi 得到匹配
if(cal(i)) break; int d = INF;
for(int i = 0; i < n; ++i)
if(!visy[i]) d = min(d,slack[i]); //匹配中的x顶标都减去d
for(int i = 0; i < n; ++i)
if(visx[i]) lx[i] -= d; //匹配中的y顶标都加上d
//否则降低slack
for(int i = 0; i < n; ++i)
if(visy[i]) ly[i] += d;
else slack[i] -= d;
}
} int ans = 0;
for(int i = 0; i < n; ++i)
if(link[i] != -1) ans += mp[link[i]][i]; return ans;
} int main()
{
while(~scanf("%d",&n))
{
memset(lx,0,sizeof(lx));
for(int i = 0; i < n; ++i)
for(int j = 0; j < n; ++j)
{
scanf("%d",&mp[i][j]);
if(mp[i][j] > lx[i]) lx[i] = mp[i][j];
} printf("%d\n",KM());
} return 0;
}
【HDOJ 2255】奔小康赚大钱(KM算法)的更多相关文章
- hdu 2255 奔小康赚大钱--KM算法模板
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2255 题意:有N个人跟N个房子,每个人跟房子都有一定的距离,现在要让这N个人全部回到N个房子里面去,要 ...
- hdu 2255奔小康赚大钱 KM算法模板
题目链接:http://acm.hdu.edu.cn/showproblem.php? pid=2255 一,KM算法:(借助这个题写一下个人对km的理解与km模板) KM算法主要是用来求解图的最优匹 ...
- HDU - 2255 奔小康赚大钱 KM算法 模板题
HDU - 2255 题意: 分配n所房子给n个家庭,不同家庭对一所房子所需缴纳的钱是不一样的,问你应当怎么分配房子,使得最后收到的钱最多. 思路: KM算法裸题.上模板 #include <i ...
- hdu 2255 奔小康赚大钱 KM算法
看到这么奇葩的题目名我笑了,后来这么一个裸的KM调了2小时我哭了…… 这是个裸的KM算法,也没什么多说的,主要是注意多组数据时,每次都要把各种数组清空啊,赋值啊什么的,反正比较麻烦.至于为什么调了2小 ...
- HDU 2255 奔小康赚大钱 KM算法的简单解释
KM算法一般用来寻找二分图的最优匹配. 步骤: 1.初始化可行标杆 2.对新加入的点用匈牙利算法进行判断 3.若无法加入新编,修改可行标杆 4.重复2.3操作直到找到相等子图的完全匹配. 各步骤简述: ...
- HDU 2255 奔小康赚大钱 KM算法题解
KM算法求的是完备匹配下的最大权匹配,是Hungary算法的进一步,由于Hungary算法是最大匹配的算法,不带权. 经典算法,想不出来的了,要參考别人的.然后消化吸收吧. 由于真的非常复杂的算法. ...
- 最大流增广路(KM算法) HDOJ 2255 奔小康赚大钱
题目传送门 /* KM:裸题第一道,好像就是hungary的升级版,不好理解,写点注释 KM算法用来解决最大权匹配问题: 在一个二分图内,左顶点为X,右顶点为Y,现对于每组左右连接Xi,Yj有权w(i ...
- hdu2255 奔小康赚大钱 km算法解决最优匹配(最大权完美匹配)
/** 题目:hdu2255 奔小康赚大钱 km算法 链接:http://acm.hdu.edu.cn/showproblem.php?pid=2255 题意:lv 思路:最优匹配(最大权完美匹配) ...
- hdu 2255 奔小康赚大钱 (KM)
奔小康赚大钱Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- 【HDU2255】奔小康赚大钱-KM算法
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem Description ...
随机推荐
- reactnative(2) - Navigator 使用案例
'use strict'; import React, { Component } from 'react'; import { AppRegistry, ScrollView, StyleSheet ...
- [ JSOI 2015 ] Salesman
\(\\\) \(Description\) 给出一棵以\(1\)为根的\(N\)个节点的树,开始的时候你在\(1\)号节点. 除了\(1\)号节点以外,每个点都有访问次数限制\(t_i\),即到达该 ...
- python--9、进程池
concurrent.futures模块 进程池中的进程是固定的,若是池中有任务结束后,等待的任务进来后由空闲的进程来处理. 导入方法三连发: from 标题的模块 import 如下:Process ...
- iOS CoreData 开发
新年新气象,曾经的妹子结婚了,而光棍的我决定书写博客~ 废话结束. 本人不爱使用第三方的东东,喜欢原汁原味的官方版本,本次带来CoreData数据存储篇~ 创建应用
- Android基础TOP2_1:输出系统时间
Activity: <TextView android:id="@+id/tv" android:layout_width="wrap_content" ...
- JavaScript的基础数据类型和表达式
Java Script的基础数据类型和表达式 基本的数据类型: number(数值)类型:可分为整数和浮点数 string(字符)类型:是用单引号“'”或者双引号“"”来说明的. boole ...
- JNI数组操作
在Java中数组分为两种: 1.基本类型数组 2.对象类型(Object[])的数组(数组中存放的是指向Java对象中的引用) 一个能通用于两种不同类型数组的函数: GetArrayLength(ja ...
- js的StringBuffer类
function StringBuffer(str){ var arr = []; str = str || ""; arr.push(str); this.append = fu ...
- 利用open MP获取计算机核心数量的方法
openMP是一款普遍通用的并行计算编程模型,使用它通常能够充分利用多核计算的优势. 以下是一种能够测试核心数量的方法: std::cout << "parallel begin ...
- Ajax基本写法
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...