/* Question: Given a n * m map, there are several man and house on the map, and the number of man and house are consistent. $1 (unit cost = unit distance) is required for a man to move one cell. Only one man can be accommodated in one house. Now all man is required to stay in the house and the minimum fee is required. The minimum cost of the maximum flow to the spfa to find the minimum cost can improve the path of imitation write http://blog.csdn.net/lyy289065406/article/details/6732762 this, here there are questions and notes, almost exactly the same, haha, learning. */# Include <iostream >#include <cmath> # include <queue> using namespace STD; Class coordinate {public: int X, Y; coordinate (){}}; class solve {public: Solve (INT row, int col): R (ROW), C (COL) {int I, j, mzz, hzz; mannum = 0; mincost = 0; Map = new char * [R]; for (I = 0; I <r; I ++) {map [I] = new char [c]; for (j = 0; j <C; j ++) {CIN> map [I] [J]; if (Map [I] [J] = 'M') + + mannum;} // locate the coordinates man = new coordinate [mannum + 1]; house = new coordinate [mannum + 1]; mzz = hzz = 0; for (I = 0; I <r; ++ I) for (j = 0; j <C; ++ J) if (Map [I] [J] = 'M') {MAN [++ mzz]. X = I; man [mzz]. y = J;} else if (Map [I] [J] = 'H') {House [++ hzz]. X = I; House [hzz]. y = J;} // create expense chart and flow chart cost = new int * [2 * mannum + 2]; flow = new int * [2 * mannum + 2]; for (I = 0; I <2 * mannum + 2; ++ I) {cost [I] = new int [2 * mannum + 2]; flow [I] = new int [2 * mannum + 2]; memset (cost [I], 0, sizeof (INT) * (2 * mannum + 2 )); // Note: memset (flow [I], 0, sizeof (INT) * (2 * mannum + 2) is not the same as the previous method ));} // initialize S = 0; t = 2 * Mannum + 1; for (I = 1; I <= mannum; ++ I) flow [s] [I] = 1; for (I = 1; I <= mannum; ++ I) for (j = 1; j <= mannum; ++ J) {cost [I] [J + mannum] = ABS (MAN [I]. x-House [J]. x) + ABS (MAN [I]. y-House [J]. y); cost [J + mannum] [I] =-cost [I] [J + mannum]; flow [I] [J + mannum] = 1 ;} for (I = mannum + 1; I <t; ++ I) flow [I] [T] = 1; // solve pre = new int [2 * mannum + 2]; memset (PRE, 0, sizeof (INT) * (2 * mannum + 2 )); dist = new int [2 * mannum + 2]; vis = new int [2 * mannum + 2]; while (spfa () // and the augmented path add (); // push stream} Int Inf () const {return 0x7fffff;} // set the maximum value of int min (int A, int B) {return a <B? A: B;} // get a smaller int spfa () // The improved path for minimum cost {Dist [s] = 0; For (INT I = 1; I <2 * mannum + 2; I ++) Dist [I] = inf (); memset (VIS, 0, sizeof (INT) * (2 * mannum + 2); vis [s] = 1; queue <int> q; q. push (s); While (! Q. empty () {int u = Q. front (); For (int v = 0; v <= T; ++ V) {If (flow [u] [v] & Dist [v]> Dist [u] + cost [u] [v]) {Dist [v] = DIST [u] + cost [u] [v]; Pre [v] = u; If (! Vis [v]) {q. push (V); vis [v] = 1 ;}} Q. pop (); vis [u] = 0;} If (Dist [T] = inf () return 0; return 1;} void add () // push stream {int maxflow = inf (); int I; for (I = T; I! = S; I = pre [I]) maxflow = min (maxflow, flow [pre [I] [I]); for (I = T; I! = S; I = pre [I]) {flow [pre [I] [I]-= maxflow; flow [I] [pre [I] + = maxflow; mincost + = cost [pre [I] [I] * maxflow;} return ;}~ Solve () // {cout <mincost <Endl; // output solution Delete [] Man; // reclaim space Delete [] House; Delete [] Dist; delete [] vis; Delete [] pre; For (INT I = 0; I <r; ++ I) Delete [] map [I]; for (Int J = 0; j <2 * mannum + 2; ++ J) {Delete [] cost [J]; Delete [] flow [J];} Delete [] map; Delete [] cost; delete [] flow;} PRIVATE: int mincost; int R, C; int ** cost, ** flow; int mannum; char ** map; coordinate * Man; coordinate * house; int S, T; int * Pre, * vis, * Dist;}; int main () {int row, Col; while (CIN> row> Col, row + col) Solve poj2195 (row, col); Return 0 ;}
When finding the shortest path, you need to determine whether there is any stream addition. when updating the distance, it is based on cost.
This question can also be done using the minimum weight match. after learning the bipartite graph, I wrote it again using the minimum weight match.
/* Poj 2195 going home learns bipartite graph matching, So it uses the minimum weight to match some sides, it is faster than the minimum cost and the maximum flow. Some minimum and maximum weight matching are similar. You only need to obtain the opposite number of edge weights. Then, the process is the same as the maximum weight matching. The last edge weight is a negative number and the opposite is obtained. you can check the number at http://blog.csdn.net/qq172108805/article/details/7855113with some instructions. /#include <iostream> # include <cmath> using namespace STD; int M, N; struct node // represents the position of a person or house {int X, Y ;}; struct edge // saves the edge in an adjacent table {int V, F, next ;} E [100000]; node * Man, * house; // int * match, * lx, * ly, * slack, * visx, * visy, * head, nman; // match the top mark of X Y top optimization array x access flag y access flag number of nodes adjacent to the header char map [110] [110]; int hungray (int I) // Hungarian algorithm {Int J, V; visx [I] = 1; for (j = head [I]; J! =-1; j = E [J]. next) {v = E [J]. v; If (visy [v]) continue; If (LX [I] + ly [v] = E [J]. f) {visy [v] = 1; if (Match [v] =-1 | hungray (Match [v]) {match [v] = I; return 1 ;}} else if (Slack [v]> lx [I] + ly [v]-E [J]. f) slack [v] = Lx [I] + ly [v]-E [J]. f;} return 0;} int km () // km {memset (match,-1, sizeof (INT) * nman); int I, j, D; memset (ly, 0, sizeof (INT) * nman); for (I = 0; I <nman; ++ I) {for (j = 0; j <nman; ++ J) slack [J] = 0x7fffffff; while (1) {memset (visx, 0, sizeof (INT) * nman ); Memset (visy, 0, sizeof (INT) * nman); If (hungray (I) break; D = 0x7fffffff; For (j = 0; j <nman; ++ J) if (! Visy [J] & slack [J] <D) d = slack [J]; for (j = 0; j <nman; ++ J) {If (visx [J]) lx [J]-= D; If (visy [J]) ly [J] + = D; else slack [J]-= D ;}} D = 0; for (I = 0; I <nman; ++ I) d ++ = Lx [I], d + = ly [I]; Return-D; // returns the opposite number} int main () {int I, j, Yong; while (CIN> N> m, m + n) {nman = 0; // initialize Yong = 0; for (I = 0; I <n; ++ I) // read data for (j = 0; j <m; ++ J) {CIN> map [I] [J]; If (Map [I] [J] = 'M') nman ++ ;} match = new int [nman]; // apply for space man = new node [nman]; // House = new node [nman]; // Lx = new int [nman]; // Ly = new int [nman]; // slack = new int [nman]; // visx = new int [nman]; // visy = new int [nman]; // head = new int [nman]; // int jman = 0, jhouse = 0; for (I = 0; I <n; ++ I) // The location of the statistician and house for (j = 0; j <m; ++ J) {If (Map [I] [J] = 'M ') {MAN [jman]. X = I; man [jman ++]. y = J;} else if (Map [I] [J] = 'H') {House [jhouse]. X = I; House [jhouse ++]. y = J ;}} memset (Head,-1, sizeof (INT) * nman); // distance between a computer and a house edge building for (I = 0; I <nman; ++ I) {int max =-(0x7fffffff); // assign a value to the LX array during calculation, that is, the maximum right of the edge connected to I (j = 0; j <nman; ++ J) {e [Yong]. V = J; E [Yong]. F =-(ABS (MAN [I]. x-House [J]. x) + ABS (MAN [I]. y-House [J]. y); // If (max <E [Yong]. f) max = E [Yong]. f; // update MaxE [Yong]. next = head [I]; head [I] = Yong ++;} lx [I] = max; // assign a value to lx} cout <km () <Endl; // computing output Delete [] match; // release space Delete [] Man; Delete [] House; Delete [] lx; Delete [] ly; Delete [] slack; delete [] visx; Delete [] visy; Delete [] Head;} return 0 ;}