HDU - 奔小康赚大钱(二分图最佳匹配+KM)
发布日期:2021-07-01 00:16:26
浏览次数:2
分类:技术文章
本文共 2615 字,大约阅读时间需要 8 分钟。
题目链接:
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Problem Description
传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子。 这可是一件大事,关系到人民的住房问题啊。村里共有n间房间,刚好有n家老百姓,考虑到每家都要有房住(如果有老百姓没房子住的话,容易引起不安定因素),每家必须分配到一间房子且只能得到一间房子。 另一方面,村长和另外的村领导希望得到最大的效益,这样村里的机构才会有钱.由于老百姓都比较富裕,他们都能对每一间房子在他们的经济范围内出一定的价格,比如有3间房子,一家老百姓可以对第一间出10万,对第2间出2万,对第3间出20万.(当然是在他们的经济范围内).现在这个问题就是村领导怎样分配房子才能使收入最大.(村民即使有钱购买一间房子但不一定能买到,要看村领导分配的).
Input
输入数据包含多组测试用例,每组数据的第一行输入n,表示房子的数量(也是老百姓家的数量),接下来有n行,每行n个数表示第i个村名对第j间房出的价格(n<=300)。
Output
请对每组数据输出最大的收入值,每组的输出占一行。
Sample Input
2
100 10 15 23
Sample Output
123
Problem solving report:
Description: 二分图最大权匹配。
Problem solving: KM模板题。建立二分图,一边为N家老百姓,另一边为N间房子。对老百姓和房子之间估价建立一条有带权边。问题就转变为了再二分图中找出一个总权值最大的匹配,也就是加权二分图最佳匹配问题。 参考博文1: 参考博文2:#include#include #include using namespace std;const int MAXN = 330;const int inf = 0xffffff0;int link[MAXN], lx[MAXN], ly[MAXN], slack[MAXN];int n, visx[MAXN], visy[MAXN], map[MAXN][MAXN];int FindPath(int u){ visx[u] = 1; for (int i = 1; i <= n; i++) { if (visy[i]) continue; int temp = lx[u] + ly[i] - map[u][i]; if (!temp) { visy[i] = 1; if (link[i] == -1 || FindPath(link[i])) { link[i] = u; return 1; } } else if (slack[i] > temp) slack[i] = temp; } return 0;}int KM(){ memset(ly, 0, sizeof(ly)); memset(link, -1, sizeof(link)); for (int i = 1; i <= n; i++) { lx[i] = -inf; for (int j = 1; j <= n; j++) if (map[i][j] > lx[i]) lx[i] = map[i][j]; } for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) slack[j] = inf; while (1) { memset(visx, 0, sizeof(visx)); memset(visy, 0, sizeof(visy)); if (FindPath(i)) break; int d = inf; for (int j = 1; j <= n; j++) if (!visy[j] && d > slack[j]) d = slack[j]; for (int j = 1; j <= n; j++) { if (visx[j]) lx[j] -= d; if (visy[j]) ly[j] += d; else slack[j] -= d; } } } int res = 0; for (int i = 1; i <= n; ++i) if (link[i] > -1) res += map[link[i]][i]; return res;}int main(){ while (~scanf("%d", &n)) { for (int i = 1; i <= n; ++i) for (int j = 1; j <= n; ++j) scanf("%d", &map[i][j]); printf("%d\n", KM()); } return 0;}
转载地址:https://lzyws739307453.blog.csdn.net/article/details/86995909 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
关注你微信了!
[***.104.42.241]2024年04月26日 02时24分27秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
HIVE自定义函数--UDF函数(用户自定义函数)详解
2019-05-01
Java中访问控制符的具体用法
2019-05-01
Java包重点总结
2019-05-01
创建线程究竟该用第几种方式
2019-05-01
Java--流重点总结初稿
2019-05-01
Java高级部分流---换个角度思考流
2019-05-01
如何解决电脑ip地址冲突的问题
2019-05-01
Win下如何查看本地计算机的网络端口被哪个应用程序所占用
2019-05-01
TCP/IP、Http、Socket的区别
2019-05-01
Java高级部分容器重点总结下
2019-05-01
Java高级部分流重点总结上
2019-05-01
Html当中文本与标签如何居中
2019-05-01
Python引用2(Django系列3)
2019-05-01
信息列表+上传文件
2019-05-01
Python中常用的模块--Log日志模块
2019-05-01
通过JS实现轮播图
2019-05-01
Django通过HttpResponse如何返回用户头像
2019-05-01
深入理解RabbitMQ消息队列的使用-张明阳-专题视频课程
2019-05-01
POJ 3320 Jessica's Reading Problem
2019-05-01
MyEclipse 2015 stable 2.0破解
2019-05-01