Topic Links:
http://poj.org/problem?id=2195
Main topic:
In a n*m matrix, there are M-individuals and M-houses, each of whom arranges a house, and each house can only be arranged by a single person.
And each person moving one step requires a dollar. So here's the question: the minimum amount of money needed to arrange a house move for everyone
Less.
Ideas:
Make a dichotomy, one side is a person, the other is a house, and if the distance between man and house is Benquan, the problem becomes
The best matching of the minimum weights and the weighted binary graphs. Here we calculate for convenience, the negative value of the distance between man and house as
Edge right, then it becomes the best matching of the right and the right of the two-dimensional graph, which is the best matching problem of the classical two-fractal graph. Use km to calculate
method to solve the maximum weight value and. To the contrary, it gets the least weight and. Template Reference Blog about the KM algorithm:
http://blog.csdn.net/lianai911/article/details/44832831
AC Code:
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include < cmath>using namespace Std;const int maxn = 110;const int INF = 0xffffff0;struct node{int x, y;} Man[maxn],house[maxn];int Dist (Node A,node b) {return-(ABS (a.x-b.x) + ABS (A.Y-B.Y));} int n,nx,ny;int map[maxn][maxn];int Link[maxn],lx[maxn],ly[maxn],slack[maxn];int visx[maxn],visy[maxn];int FindPath (int u) {Visx[u] = 1; for (int i = 1; I <= NY; ++i) {if (visy[i]) continue; int temp = Lx[u] + ly[i]-map[u][i]; if (temp = = 0) {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 <= NX; ++i) {lx[i] =-inf; for (int j = 1; j <= NY;++J) if (Map[i][j] > Lx[i]) lx[i] = Map[i][j]; } for (int i = 1; I <= NX; ++i) {for (int j = 1; j <= NY; ++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 <= NY; ++j) if (!visy[j] && d > slack[j]) d = slack[j]; for (int j = 1; j <= NX; ++j) if (Visx[j]) lx[j]-= D; for (int j = 1; j <= NY; ++j) if (Visy[j]) ly[j] + = D; else Slack[j]-= D; }} int res = 0; for (int i = 1; I <= NY; ++i) if (Link[i] >-1) Res + = Map[link[i]][i]; return res;} int main () {int n,m,mannum,housenum; Char ch; while (~SCANF ("%d%d", &n,&m) && (n| | M) {Mannum = HouseNum = 1; for (int i = 1; I <= N; ++i) {GetChar (); for (int j = 1; j <= M; ++j) {scanf ("%c", &ch); if (ch = = ' m ') {man[mannum].x = i; Man[mannum++].y = j; } else if (ch = = ' H ') {house[housenum].x = i; House[housenum++].y = j; }}} NX = NY = ManNum-1; for (int i = 1; I <= NX; ++i) {for (int j = 1; j <= NY; ++j) {map[i][j] = Dist (Man[i],house[j]); }} printf ("%d\n",-km ()); } return 0;}
POJ2195 going Home "Two-point graph best Match"