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

题意:给个图,m代表人H代表房子。每一个m要有一个H,代价是曼哈顿距离。问让所有m找到房子的最小花费。

可以直接枚举m和H建二分图跑KM。

  1 #include <algorithm>
  2 #include <iostream>
  3 #include <iomanip>
  4 #include <cstring>
  5 #include <climits>
  6 #include <complex>
  7 #include <cassert>
  8 #include <cstdio>
  9 #include <bitset>
 10 #include <vector>
 11 #include <deque>
 12 #include <queue>
 13 #include <stack>
 14 #include <ctime>
 15 #include <set>
 16 #include <map>
 17 #include <cmath>
 18
 19 using namespace std;
 20
 21 const int maxn = 310;
 22 const int inf = 0x3f3f3f3f;
 23 int nx,ny;
 24 int G[maxn][maxn];
 25 int linker[maxn],lx[maxn],ly[maxn];
 26 int slack[maxn];
 27 bool visx[maxn],visy[maxn];
 28
 29 bool dfs(int x) {
 30     visx[x] = true;
 31     for(int y = 0; y < ny; y++) {
 32         if(visy[y])continue;
 33         int tmp = lx[x] + ly[y] - G[x][y];
 34         if(tmp == 0) {
 35             visy[y] = true;
 36             if(linker[y] == -1 || dfs(linker[y])) {
 37                 linker[y] = x;
 38                 return true;
 39             }
 40         }
 41         else if(slack[y] > tmp)
 42             slack[y] = tmp;
 43     }
 44     return false;
 45 }
 46 int km() {
 47     memset(linker,-1,sizeof(linker));
 48     memset(ly,0,sizeof(ly));
 49     for(int i = 0;i < nx;i++) {
 50         lx[i] = -inf;
 51         for(int j = 0;j < ny;j++)
 52             if(G[i][j] > lx[i])
 53                 lx[i] = G[i][j];
 54     }
 55     for(int x = 0;x < nx;x++) {
 56         for(int i = 0;i < ny;i++)
 57             slack[i] = inf;
 58         while(true) {
 59             memset(visx,false,sizeof(visx));
 60             memset(visy,false,sizeof(visy));
 61             if(dfs(x))break;
 62             int d = inf;
 63             for(int i = 0;i < ny;i++)
 64                 if(!visy[i] && d > slack[i])
 65                     d = slack[i];
 66             for(int i = 0;i < nx;i++)
 67                 if(visx[i])
 68                     lx[i] -= d;
 69             for(int i = 0;i < ny;i++) {
 70                 if(visy[i])ly[i] += d;
 71                 else slack[i] -= d;
 72             }
 73         }
 74     }
 75     int res = 0;
 76     for(int i = 0;i < ny;i++)
 77         if(linker[i] != -1)
 78             res += G[linker[i]][i];
 79     return res;
 80 }
 81
 82 typedef pair<int,int> pii;
 83 char mp[maxn][maxn];
 84 int n, m;
 85 vector<pii> h, p;
 86
 87 int main() {
 88   // freopen("in", "r", stdin);
 89     while(~scanf("%d%d",&n,&m) && n+m) {
 90         memset(mp, 0, sizeof(mp));
 91         h.clear(); p.clear();
 92         for(int i = 1; i <= n; i++) {
 93             scanf("%s", mp[i]+1);
 94         }
 95         for(int i = 1; i <= n; i++) {
 96             for(int j = 1; j <= m; j++) {
 97                 if(mp[i][j] == 'H') h.push_back(pii(i, j));
 98                 else if(mp[i][j] == 'm') p.push_back(pii(i, j));
 99             }
100         }
101         memset(G, 0, sizeof(G));
102         nx = h.size(); ny = p.size();
103         for(int i = 0; i < h.size(); i++) {
104             for(int j = 0; j < p.size(); j++) {
105                 int dis = abs(h[i].first - p[j].first) + abs(h[i].second - p[j].second);
106                 G[i][j] = -dis;
107             }
108         }
109         printf("%d\n", -km());
110     }
111     return 0;
112 }

KM

也可以用最小费用流建模。

  1 #include <algorithm>
  2 #include <iostream>
  3 #include <iomanip>
  4 #include <cstring>
  5 #include <climits>
  6 #include <complex>
  7 #include <cassert>
  8 #include <cstdio>
  9 #include <bitset>
 10 #include <vector>
 11 #include <deque>
 12 #include <queue>
 13 #include <stack>
 14 #include <ctime>
 15 #include <set>
 16 #include <map>
 17 #include <cmath>
 18
 19 using namespace std;
 20
 21 typedef long long LL;
 22 typedef struct Node {
 23     int u, v, next;
 24     LL c, w;
 25 }Node;
 26 const int maxn = 20010;
 27 const int maxm = 40010;
 28 const LL mod = 0x3f3f3f3fLL;
 29 const LL inf = (1LL<<55);
 30 int tot, head[maxn];
 31 LL dist[maxn];
 32 LL cost, flow;
 33 Node e[maxm];
 34 int pre[maxn];
 35 bool visit[maxn];
 36 queue<int> Q;
 37 int S, T, N;
 38
 39 void init() {
 40     S = T = N = 0;
 41     memset(head, -1, sizeof(head));
 42     tot = 0;
 43 }
 44
 45 void adde(int u, int v, LL c, LL w) {
 46     e[tot].u = u; e[tot].v = v; e[tot].c = c; e[tot].w = w; e[tot].next = head[u]; head[u] = tot++;
 47     e[tot].u = v; e[tot].v = u; e[tot].c = 0; e[tot].w = -w; e[tot].next = head[v]; head[v] = tot++;
 48 }
 49 bool spfa(int s, int t, int n) {
 50     int i;
 51     for(i = 0; i <= n; i++) {
 52         dist[i] = inf;
 53         visit[i] = 0;
 54         pre[i] = -1;
 55     }
 56     while(!Q.empty()) Q.pop();
 57     Q.push(s);
 58     visit[s] = true;
 59     dist[s] = 0;
 60     pre[s] = -1;
 61     while(!Q.empty()) {
 62         int u = Q.front();
 63         visit[u] = false;
 64         Q.pop();
 65         for(int j = head[u]; j != -1; j = e[j].next) {
 66             if(e[j].c > 0 && dist[u] + e[j].w < dist[e[j].v]) {
 67                 dist[e[j].v] = dist[u] + e[j].w;
 68                 pre[e[j].v] = j;
 69                 if(!visit[e[j].v]) {
 70                     Q.push(e[j].v);
 71                     visit[e[j].v] = true;
 72                 }
 73             }
 74         }
 75     }
 76     if(dist[t] == inf) return false;
 77     else return true;
 78 }
 79 LL ChangeFlow(int t) {
 80     LL det = mod;
 81     int u = t;
 82     while(~pre[u]) {
 83         u = pre[u];
 84         det = min(det, e[u].c);
 85         u = e[u].u;
 86     }
 87     u = t;
 88     while(~pre[u]) {
 89         u = pre[u];
 90         e[u].c -= det;
 91         e[u ^ 1].c += det;
 92         u = e[u].u;
 93     }
 94     return det;
 95 }
 96 LL MinCostFlow(int s, int t, int n) {
 97     LL mincost, maxflow;
 98     mincost = maxflow = 0;
 99     while(spfa(s, t, n)) {
100         LL det = ChangeFlow(t);
101         mincost += det * dist[t];
102         maxflow += det;
103     }
104     cost = mincost;
105     flow = maxflow;
106     return mincost;
107 }
108
109 typedef pair<int,int> pii;
110 char mp[111][111];
111 int n, m;
112 vector<pii> h, p;
113
114 int main() {
115   // freopen("in", "r", stdin);
116     while(~scanf("%d%d",&n,&m) && n+m) {
117         init();
118         memset(mp, 0, sizeof(mp));
119         h.clear(); p.clear();
120         for(int i = 1; i <= n; i++) {
121             scanf("%s", mp[i]+1);
122         }
123         for(int i = 1; i <= n; i++) {
124             for(int j = 1; j <= m; j++) {
125                 if(mp[i][j] == 'H') h.push_back(pii(i, j));
126                 else if(mp[i][j] == 'm') p.push_back(pii(i, j));
127             }
128         }
129         S = 0, T = h.size() + p.size() + 1, N = T + 1;
130         for(int i = 0; i < h.size(); i++) adde(S, i+1, 1, 0);
131         for(int i = 0; i < p.size(); i++) adde(h.size()+i+1, T, 1, 0);
132         for(int i = 0; i < h.size(); i++) {
133             for(int j = 0; j < p.size(); j++) {
134                 int dis = abs(h[i].first - p[j].first) + abs(h[i].second - p[j].second);
135                 int hi = i + 1;
136                 int pi = h.size() + j + 1;
137                 adde(hi, pi, 1, (LL)dis);
138             }
139         }
140         cout << MinCostFlow(S, T, N) << endl;
141     }
142     return 0;
143 }

转载于:https://www.cnblogs.com/kirai/p/6769135.html

[POJ2195]Going Home(带权最大匹配,KM,最小费用流)相关推荐

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

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

  2. 二分图大讲堂——彻底搞定最大匹配数(最小覆盖数)、最大独立数、最小路径覆盖、带权最优匹配

    二分图匹配 二分图大讲堂--彻底搞定最大匹配数(最小覆盖数).最大独立数.最小路径覆盖.带权最优匹配(转) 文本内容框架: §1图论点.边集和二分图的相关概念和性质 §2二分图最大匹配求解 匈牙利算法 ...

  3. Uvalive3353 Optimal Bus Route Design 带权二分图匹配

    题目描述:给出一个有向带权图,现在要求在图中找出若干个环,使得每个点恰好在一个环里,且所有环的距离之和最小,如果不能使每个点恰好在一个环里,输出"N". 思路: 将每个点u拆成u和 ...

  4. POJ-2195 Going Home 最小权值匹配

    题意:给定一个网格图,图上有一些人要到一些房子当中去,人和房子的数量一样多,人和房子的曼哈顿距离作为行走的开销,问所有人走到房子中的最小开销. 解法:将人和房子之间两两之间建立带权边,权值为曼哈顿距离 ...

  5. HOJ 2739 The Chinese Postman Problem 带权有向图上的中国邮路问题

    [题目大意]  带权有向图上的中国邮路问题:一名邮递员需要经过每条有向边至少一次,最后回到出发点,一条边多次经过权值要累加,问最小总权值是多少.(2 <= N <= 100, 1 < ...

  6. 带权二分图匹配(最小费用最大流) 8.2牛客暑期多校训练营五 E

    E.room | 时间限制:1 秒 | 内存限制:256M Nowcoder University has 4n students and n dormitories ( Four students ...

  7. 语音识别、传统语音识别、带权有限转态转换器、深度语音识别、时序分类、CTC解码

    语音识别.传统语音识别.带权有限转态转换器.深度语音识别.时序分类.CTC解码 目录

  8. 2017乌鲁木齐区域赛I(带权并查集)

    #include<bits/stdc++.h> using namespace std; int f[200010];//代表元 long long rl[200010];//记rl[i] ...

  9. BZOJ 2303 方格染色(带权并查集)

    要使得每个2*2的矩形有奇数个红色,如果我们把红色记为1,蓝色记为0,那么我们得到了这2*2的矩形里的数字异或和为1. 对于每个方格则有a(i,j)^a(i-1,j)^a(i,j-1)^a(i-1,j ...

  10. POJ1703带权并查集(距离或者异或)

    题意:       有两个黑社会帮派,有n个人,他们肯定属于两个帮派中的一个,然后有两种操作 1 D a b 给出a b 两个人不属于同一个帮派 2 A a b 问a b 两个人关系 输出 同一个帮派 ...

最新文章

  1. 移动APP开发使用什么样的原型设计工具比较合适?
  2. 台湾大学林轩田机器学习基石课程学习笔记10 -- Logistic Regression
  3. 【iMX6ULL】触觉 imx6ull开发板交叉编译环境搭建
  4. 【转】java io 总结(图)
  5. mysql select效率_Mysql优化之selectcount效率_MySQL
  6. (转)向SDE库中写入栅格和矢量数据
  7. ae导出gif插件_AE小白必看教程,围观AE老司机如何使用AE导出gif图片
  8. 今天开通android博客 该认真学习了
  9. 278.第一个错误版本(力扣leetcode) 博主可答疑该问题
  10. 手把手教你DosBox的配置(附下载资源)
  11. python入门学习随记(十二)
  12. Excise_day01
  13. 路由器wan口认证断开服务器无响应,路由器WAN口设置已断开(服务器无响应)的解决方法...
  14. WPS/WORD论文格式调整方法
  15. 照片墙(3D立体几何)
  16. 王道计算机组成原理第六章---总线总结
  17. 【清华牛人】Stanford, Caltech双料博士
  18. 讲解Guitar Pro 7使用向导的技巧
  19. MySQL的limit分页,为什么越往后翻越慢,怎么解决?
  20. java emoji过滤_Android中过滤Emoji表情 完整版

热门文章

  1. 【openjudge】字符串排序
  2. 已有一个名为“frmadd”的组件。组件的名称必须是唯一的,而且名称必须不区分大小
  3. 你可能不知道的CSS3属性: object-fit,object-position的妙用
  4. Java神鬼莫测之MyBatis实现分页全过程(三)
  5. 仍然提供32位Linux发行版,Ubuntu 20.04彻底淘汰32位映像,只提供64位映像下载
  6. python中format函数怎么样提取字符串里的字符_Python中用format函数格式化字符串的用法...
  7. java应用中如何连接dbproxy_GitHub - alchemystar/hero: 用c语言写的dbproxy
  8. 如何手绘表格_Word2010中怎样用画笔绘制表格
  9. java序列化和反序列化练习
  10. 服务器win10系统开机慢,Win10系统开机慢怎么办 windows10开机慢的解决方法