题意:

有 n 个房子和 n 个人

每个人走一个单元你就要付 1$

有什么办法可以让把所有人都分派到房子里 而花费最少

输入:

  给出n m 表示该矩阵由n 行 m 列组成

  然后给出一个n*m的图

  . 表示空地 H 表示房子 m 表示人

思路:

二分图最佳匹配<有权还要完全匹配>

Tips:

建图很有趣~

Code:

View Code

  1 #include <stdio.h>
  2 #include <cstring>
  3 #include <cmath>
  4 #define M 110
  5 #define inf 0x1f1f1f1f
  6
  7 struct Node
  8 {
  9     int x;
 10     int y;
 11 }man[110], home[110];
 12
 13 int n,nx,ny;
 14 int link[M],lx[M],ly[M],slack[M];    //lx,ly为顶标,nx,nx分别为x点集y点集的个数
 15 int visx[M],visy[M],w[M][M];
 16
 17 int DFS(int x)
 18 {
 19     visx[x] = 1;
 20     for (int y = 1;y <= nx;y ++)
 21     {
 22         if (visy[y])
 23             continue;
 24         int t = lx[x] + ly[y] - w[x][y];
 25         if (t == 0)       //
 26         {
 27             visy[y] = 1;
 28             if (link[y] == -1||DFS(link[y]))
 29             {
 30                 link[y] = x;
 31                 return 1;
 32             }
 33         }
 34         else if (slack[y] > t)  //不在相等子图中slack 取最小的
 35             slack[y] = t;
 36     }
 37     return 0;
 38 }
 39 int KM()
 40 {
 41     int i,j;
 42     memset (link,-1,sizeof(link));
 43     memset (ly,0,sizeof(ly));
 44     for (i = 1;i <= nx;i ++)            //lx初始化为与它关联边中最大的
 45         for (j = 1,lx[i] = -inf;j <= nx;j ++)
 46             if (w[i][j] > lx[i])
 47                 lx[i] = w[i][j];
 48
 49     for (int x = 1;x <= nx;x ++)
 50     {
 51         for (i = 1;i <= nx;i ++)
 52             slack[i] = inf;
 53         while (1)
 54         {
 55             memset (visx,0,sizeof(visx));
 56             memset (visy,0,sizeof(visy));
 57             if (DFS(x))     //若成功(找到了增广轨),则该点增广完成,进入下一个点的增广
 58                 break;  //若失败(没有找到增广轨),则需要改变一些点的标号,使得图中可行边的数量增加。
 59                         //方法为:将所有在增广轨中(就是在增广过程中遍历到)的X方点的标号全部减去一个常数d,
 60                         //所有在增广轨中的Y方点的标号全部加上一个常数d
 61             int d = inf;
 62             for (i = 1;i <= nx;i ++)
 63                 if (!visy[i]&&d > slack[i])
 64                     d = slack[i];
 65             for (i = 1;i <= nx;i ++)
 66                 if (visx[i])
 67                     lx[i] -= d;
 68             for (i = 1;i <= nx;i ++)  //修改顶标后,要把所有不在交错树中的Y顶点的slack值都减去d
 69                 if (visy[i])
 70                     ly[i] += d;
 71                 else
 72                     slack[i] -= d;
 73         }
 74     }
 75     int res = 0;
 76     for (i = 1;i <= nx;i ++)
 77         if (link[i] > -1)
 78             res += w[link[i]][i];
 79     return -res;
 80 }
 81
 82 int main ()
 83 {
 84     int i, j, k;
 85     int m;
 86     char G[110][110];
 87     while (scanf("%d %d", &n, &m)!=EOF)
 88     {
 89         if(n == 0 && m == 0) break;
 90         nx = 1, ny = 1;
 91       //  memset (w,0,sizeof(w));
 92       getchar();
 93       for(i = 0; i < n; ++i)
 94         gets(G[i]);
 95
 96       for(i = 0; i < n; ++i)
 97       for(j = 0; j < m; ++j) {
 98         if(G[i][j] == 'm') {
 99             man[nx].x = i;
100             man[nx++].y = j;
101         }
102         else if(G[i][j] == 'H') {
103             home[ny].x = i;
104             home[ny++].y = j;
105         }
106       }
107
108       for(i = 1; i < nx; ++i)
109       for(j = 1; j < ny; ++j) {
110         w[i][j] = -fabs(man[i].x - home[j].x) - fabs(man[i].y - home[j].y);
111       }
112
113         nx--;
114         int ans = KM();
115         printf ("%d\n",ans);
116     }
117     return 0;
118 }

题目链接:http://poj.org/problem?id=2195

转载于:https://www.cnblogs.com/Griselda/archive/2012/09/28/2706534.html

POJ 2195 【二分图最佳匹配】.cpp相关推荐

  1. HDU - 奔小康赚大钱(二分图最佳匹配+KM)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2255 Time Limit: 1000/1000 MS (Java/Others) Memory Li ...

  2. POJ365Ants_二分图最佳匹配

    https://blog.csdn.net/lianai911/article/details/44835659 题意: 在坐标系中有N只蚂蚁,N棵苹果树,给你蚂蚁和苹果树的坐标.让每只蚂蚁去一棵苹果 ...

  3. 二分图最佳匹配 KM算法 Hdu2255奔小康赚大钱 + Poj 3565 Ants

    2014-10-4 更新 在最下面增加了基于邻接表的模板 理论:http://blog.sina.com.cn/s/blog_691ce2b701016reh.html http://philosci ...

  4. UVA-1045 - The Great Wall Game(二分图最佳匹配)

    题意:在一个n*n的棋盘上有n个棋子,要求通过移动棋子使棋子的排布满足以下情况之一:呈横行排列:呈纵行排列:呈对角线排列(有两条). 棋子移动一个单元格的费用为1,总费用为所有棋子的移动费用之和.求最 ...

  5. 【二分图最佳匹配】丘比特的烦恼

    丘比特的烦恼(Cupid.exe) 随着社会的不断发展,人与人之间的感情越来越功利化.最近,爱神丘比特发现,爱情也已不再是完全纯洁的了.这使得丘比特很是苦恼,他越来越难找到合适的男女,并向他们射去丘比 ...

  6. UVALive - 3353 Optimal Bus Route Design(二分图最佳匹配)

    题目大意:给出一个n个点的有向带权图,找若干个圈,使得每个节点恰好属于一个圈,要求总长度尽量小 解题思路:首先要在一个圈内,且只能在一个圈内,那么每个点的入度和出度要都为1,所以二分图就有了 接着连边 ...

  7. HDU 2255 二分图最佳匹配 模板题

    题目大意: 给定每一个人能支付的房子价值,每个人最多且必须拥有一套房子,问最后分配房子可得到的最大收益 抄了个别人的KM模板,就这样了... 1 #include <cstdio> 2 # ...

  8. KM算法 最优匹配(最大权匹配) hdu 2255 奔小康赚大钱 最小权匹配 poj 2195 Going Home

    最大权二分匹配问题就是给二分图的每条边一个权值,选择若干不相交的边,得到的总权值最大.解决这个问题可以用KM算法.理解KM算法需要首先理解"可行顶标"的概念.可行顶标是指关于二分图 ...

  9. UVA - 1045 The Great Wall Game(二分图最佳完美匹配)

    题目大意:给出棋盘上的N个点的位置.如今问将这些点排成一行或者一列.或者对角线的最小移动步数(每一个点都仅仅能上下左右移动.一次移动一个) 解题思路:暴力+二分图最佳完美匹配 #include < ...

最新文章

  1. 集成Lua到你的Android游戏(常见问题补充,解决,)
  2. java 无法找到ant_无法找到与ANT(mac)关联的文件
  3. android控制音量加减命令 python_盘点5种基于Python生成的个性化语音方法
  4. matlab的数值计算功能,MATlAB数值计算功能
  5. MySQL利用存储过程清除所有表中的所有记录
  6. c语言编程输出所有水仙花数,c语言中,如何输出所有的水仙花数
  7. C:C++ 函数返回多个参数
  8. VMware安装Linux(CentOS7)
  9. 《Linux内核分析》 week6作业-Linux内核fork()系统调用的创建过程
  10. 声艺数字调音台si说明书32路_Soundcraft 声艺 Si Impact 数字调音台 32路数字调音台...
  11. 传感器的原理及应用有哪些
  12. Android蓝牙源码分析——BTA层消息分发
  13. 文本预处理:词袋模型(bag of words,BOW)、TF-IDF
  14. 【论文浅读】《Deep Pyramidal Residual Networks for Spectral–Spatial Hyperspectral Image Classification》
  15. 周杰:推荐只是一个新的信息的传播方式
  16. 谈谈keep-alive的理解
  17. 为什么Windows Mobile会失败?
  18. 华为P20 如时升Android 9.0,华为P20系列升级EMUI9.0之后简直太流畅太完美!
  19. uniapp拍卖商城源码功能解说
  20. 2021年全国大学生软件测试大赛web应用测试预选赛试题及答案

热门文章

  1. 样本量很少如何获得最佳的效果?最新小样本学习工具包来啦!
  2. 竞赛推荐:openEuler 高校开发者大赛启动!
  3. Mobile-LPR——面向移动端的准商业级车牌识别库
  4. 美国防部DARPA发起地下空间挑战赛提供3百万美元巨奖
  5. matlab 等势面立体图,求助大牛MATLAB画三维等势面
  6. 如何在windows上搭建mysql_如何在Windows上安装多个MySQL
  7. 【Python】Python实战从入门到精通之五 -- 教你使用文件写入
  8. python爬虫学习:电商数据分析
  9. python工程师工资状况_【python工程师工资|python工程师待遇怎么样】-看准网
  10. Centos7 下部署yapi 详细教程