POJ 2195 Going Home 【二分图最小权值匹配】

传送门:http://poj.org/problem?id=2195

Going Home

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 26151   Accepted: 13117

Description

On a grid map there are n little men and n houses. In each unit time, every little man can move one unit step, either horizontally, or vertically, to an adjacent point. For each little man, you need to pay a $1 travel fee for every step he moves, until he enters a house. The task is complicated with the restriction that each house can accommodate only one little man.

Your task is to compute the minimum amount of money you need to pay in order to send these n little men into those n different houses. The input is a map of the scenario, a ‘.‘ means an empty space, an ‘H‘ represents a house on that point, and am ‘m‘ indicates there is a little man on that point. 

You can think of each point on the grid map as a quite large square, so it can hold n little men at the same time; also, it is okay if a little man steps on a grid with a house without entering that house.

Input

There are one or more test cases in the input. Each case starts with a line giving two integers N and M, where N is the number of rows of the map, and M is the number of columns. The rest of the input will be N lines describing the map. You may assume both N and M are between 2 and 100, inclusive. There will be the same number of ‘H‘s and ‘m‘s on the map; and there will be at most 100 houses. Input will terminate with 0 0 for N and M.

Output

For each test case, output one line with the single integer, which is the minimum amount, in dollars, you need to pay.

Sample Input

2 2
.m
H.
5 5
HH..m
.....
.....
.....
mm..H
7 8
...H....
...H....
...H....
mmmHmmmm
...H....
...H....
...H....
0 0

Sample Output

2
10
28

题意概括:

给一个长为 H 宽为 W 的地图,地图上 m 代表人, H 代表家,求所有人回到家的最小权值之和。(人到家的距离为 哈密顿距离)

解题思路:

拆点建二分图,距离反转,KM算法求二分图的最大权值匹配,那么去掉负号最大的就是最小的权值之和了。

AC code:

  1 #include <cstdio>
  2 #include <iostream>
  3 #include <algorithm>
  4 #include <cstring>
  5 #define INF 0x3f3f3f3f
  6 using namespace std;
  7 const int MAXN = 110;
  8
  9 char str[MAXN][MAXN];
 10 int c[MAXN][MAXN];
 11 int ex[MAXN], ey[MAXN];
 12 bool visx[MAXN], visy[MAXN];
 13 int match[MAXN];
 14 int HH, WW;
 15 int numx, numy;
 16
 17 struct date
 18 {
 19     int x, y;
 20 }M[MAXN], H[MAXN];
 21
 22 bool dfs(int x)
 23 {
 24     visx[x] = true;
 25
 26     for(int y = 0; y < numx; y++){
 27         if(!visy[y] && ex[x]+ey[y]-c[x][y] == 0){
 28             visy[y] = true;
 29
 30             if(match[y] == -1 || dfs(match[y])){
 31                 match[y] = x;
 32                 return true;
 33             }
 34         }
 35     }
 36     return false;
 37 }
 38
 39 void KM()
 40 {
 41     memset(ey, 0, sizeof(ey));
 42     memset(match, -1, sizeof(match));
 43
 44     for(int i = 0; i < numx; i++){
 45         ex[i] = c[i][0];
 46         for(int j = 1; j < numx; j++){
 47             if(c[i][j] > ex[i])
 48                 ex[i] = c[i][j];
 49         }
 50     }
 51
 52     for(int i = 0; i < numx; i++){
 53         while(1){
 54             memset(visx, 0, sizeof(visx));
 55             memset(visy, 0, sizeof(visy));
 56
 57             if(dfs(i)) break;
 58
 59             int d = INF;
 60             for(int j = 0; j < numx; j++){
 61                 if(visx[j]){
 62                     for(int k = 0; k < numx; k++){
 63                         if(!visy[k] && ex[j]+ey[k]-c[j][k] < d)
 64                             d = ex[j] + ey[k] - c[j][k];
 65                     }
 66                 }
 67             }
 68
 69             for(int j = 0; j < numx; j++){
 70                 if(visx[j]) ex[j]-=d;
 71                 if(visy[j]) ey[j]+=d;
 72             }
 73         }
 74     }
 75
 76     int res = 0;
 77     for(int i = 0; i <numx; i++){
 78         res+=c[match[i]][i];
 79     }
 80     printf("%d\n", -res);
 81 }
 82
 83 int main()
 84 {
 85     while(~scanf("%d %d", &HH, &WW) && (HH+WW)){
 86         numx = numy = 0;
 87         for(int i = 0; i < HH; i++){
 88             scanf("%s", &str[i]);
 89
 90             for(int j = 0; j < WW; j++){
 91                 if(str[i][j] == ‘m‘){
 92                     M[numx].x = i;
 93                     M[numx++].y = j;
 94                 }
 95                 else if(str[i][j] == ‘H‘){
 96                     H[numy].x = i;
 97                     H[numy++].y = j;
 98                 }
 99             }
100         }
101
102         for(int i = 0; i < numx; i++){
103             for(int j = 0; j < numx; j++)
104                 c[i][j] = -(abs(M[i].x - H[j].x) + abs(M[i].y - H[j].y));
105         }
106         KM();
107     }
108     return 0;
109 }

原文地址:https://www.cnblogs.com/ymzjj/p/10004591.html

时间: 2024-10-11 18:53:28

POJ 2195 Going Home 【二分图最小权值匹配】的相关文章

POJ 3686 The Windy&#39;s 最小权值匹配

点击打开链接 The Windy's Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 3788   Accepted: 1630 Description The Windy's is a world famous toy factory that owns M top-class workshop to make toys. This year the manager receives N orders for toys.

poj 2195 Going Home 二分图最小权匹配KM算法

题意: 有n个人要回到n间房子里,每间房子只允许一个人,求n个人要走的最小距离和. 分析: 裸的二分图最小权匹配,KM搞之. 代码: //poj 2195 //sep9 #include <iostream> using namespace std; const int maxN=128; char g[maxN][maxN]; int mx[maxN],my[maxN],hx[maxN],hy[maxN]; int w[maxN][maxN]; int lx[maxN],ly[maxN],l

POJ-2195 Going Home---KM算法求最小权值匹配(存负边)

题目链接: https://vjudge.net/problem/POJ-2195 题目大意: 给定一个N*M的地图,地图上有若干个man和house,且man与house的数量一致.man每移动一格需花费$1(即单位费用=单位距离),一间house只能入住一个man.现在要求所有的man都入住house,求最小费用. 思路: KM算法传送门: 理解篇    运用篇 每个man和house建立带权二分图,曼哈顿距离就是边的值,这里要求最小费用,也就是二分图最小权值匹配,但是KM算法求的是二分图最

UVa 1349 (二分图最小权完美匹配) Optimal Bus Route Design

题意: 给出一个有向带权图,找到若干个圈,使得每个点恰好属于一个圈.而且这些圈所有边的权值之和最小. 分析: 每个点恰好属于一个有向圈 就等价于 每个点都有唯一后继. 所以把每个点i拆成两个点,Xi 和 Yi ,然后求二分图最小权完美匹配(流量为n也就是满载时,就是完美匹配). 1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 const int maxn = 200 + 10; 6 const int INF = 10000000

POJ 2404 Jogging Trails(最小权完美匹配)

[题目链接] http://poj.org/problem?id=2404 [题目大意] 给出一张图,求走遍所有的路径至少一次,并且回到出发点所需要走的最短路程 [题解] 如果图中所有点为偶点,那么一定存在欧拉回路, 否则一定存在偶数个奇点,将这些奇点取出构建新图, 任意两点之间的边权威原图中两点的最短距离, 用状压DP求最小权完美匹配,加上原图所有边权和就是答案. [代码] #include <cstdio> #include <algorithm> #include <c

POJ 2195 二分图最小权匹配KM算法

本来是打算昨天晚上写的, 昨天网速渣的连CSDN都进不去,没办法 只能现在来写了 先写写对KM算法的理解,KM算法是对每个点设置一个顶标,只有当边长等于两边点的顶标之和的时候才进行增广,这样就能保证得到的一定是最大权匹配. 如果找不到匹配的时候就对交替路中X集合的顶标减少一个d Y集合的顶标增加一个d. 这样两个点都在交替路中的时候x[i]+y[i]的和不边 X在 Y不在的时候x[i]+y[i]减少,可能就会为图增加一对匹配. X不在Y在的时候x[i]+y[i]增加, 原来不在现在依然不在其中.

POJ 2195 Going Home(BFS+KM求最小权值)

Description: On a grid map there are n little men and n houses. In each unit time, every little man can move one unit step, either horizontally, or vertically, to an adjacent point. For each little man, you need to pay a $1 travel fee for every step

[ACM] POJ 3686 The Windy&#39;s (二分图最小权匹配,KM算法,特殊建图)

The Windy's Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 4158   Accepted: 1777 Description The Windy's is a world famous toy factory that owns M top-class workshop to make toys. This year the manager receivesN orders for toys. The man

POJ 2253 Frogger(Dijkstra变形——最短路径最小权值)

题目链接: http://poj.org/problem?id=2253 Description Freddy Frog is sitting on a stone in the middle of a lake. Suddenly he notices Fiona Frog who is sitting on another stone. He plans to visit her, but since the water is dirty and full of tourists' suns