トピックリンク:POJ-2195は、ゴーイング・ホーム
問題の意味
与えられた$ N $ $ M $は、列線グリッドは、「M」 'はHが家を示し、人を表しており、同じ数の「M」と「H」は、人は家、家を入力することができますあなただけの1水平方向と垂直方向の両方乗り出す、と今、誰もが家を入力すること、人、および最短経路に行くことができます。
考え
これは、最小の重みマッチング問題を有する二部グラフは、最小コスト、最大流量を直接解決することが可能です。
1の全てであっても、容量、コスト面0各家に一人一人の人々にソースが1の容量も1の容量をシンクするために、各家のコストエッジまでの距離を接続され、コストが0側であります最小コスト最大流量に走りました。
コードの実装
書式#include <iostreamの> の#include <cstdioを> する#include <ベクトル> の#include <キュー> の#include <cstdlib> 書式#include <CStringの> に#define N 5000 使って 名前空間はstdを、 typedefのペア < int型、int型 > P; const int型 INF = 0x3f3f3f3f 。 構造体のエッジ { int型、キャップ、コスト、REVに、 エッジ(INT T、INT C、INT CC、INT R)(t)は、キャップ(C)に、コスト(CC)、REV(R){} }; int型V。 ベクトル <エッジ> G [N]。 int型H [N]。 INTのDIST [N]。 INT prevv [N]。 int型preve [N]。 ボイド addedge(INT から、INTに、int型のキャップ、int型のコスト) { [G から.push_back](エッジ(に、キャップ、コスト、[する] G .size()))。 .push_back【に】G((エッジから、0 [G、-COST、から).size(] - 1 ))。 } INT min_cost_flow(INT S、int型T) { int型 RES =0 ; フィル(H、H + V、0 ); 一方、(真) { PRIORITY_QUEUE <P、ベクトル<P>、大きな<P>> Q。 フィル(DIST、DIST + V、INF)。 DIST [S] = 0 ; q.push(P(0 、S))。 一方、(!q.empty()) { P、P = q.top()。q.pop(); int型の V = p.second。 もし(DIST [V] <p.first)続けます。 にとって(int型 I = 0 ; iが++; iが[V] .size()Gを< ) { エッジ&E = [I] G [V]。 もし(e.cap> 0 && DIST [e.to]> DIST [V] e.cost + H + [V] - H [e.to]) { DIST [e.to] = DIST [V] + E .cost + H [V] - H [e.to]。 prevv [e.to] = V。 preve [e.to] = I。 q.push(P(DIST [e.to]、e.to))。 } } } もし(DIST [T] == INF)休憩。 用(INT J = 0 ; J <V、J ++ ) H [J] + = DIST [J]。 int型 D = INF。 用(INT ; X = Sで!X = X = T prevv [X]) D = 分(D、G [prevv [X]] [preve [X]]キャップ。)。 もし(dは== 0)ブレーク。 RES + =のD *の時間[T]。 用(INT ; X = Sであり、X = T!X = prevv [X]) { エッジ&E =){ G [prevv [X]] [preve [X]]。 e.cap - = D; G [X] [e.rev]の.cap + = D。 } } 戻りRES。 } int型のmain() { int型、N M。 一方、(〜のscanf(" %D%dの"、&N、&M)&& N && M){ ベクトル <P> HOU、人; char型のCH; 用(int型 iは= 0 ; iがN <I ++は{) のために(INT J = 0 ; J <M、J ++ scanf関数(" %のC "、&CH); もし(CH == ' H ' )hou.push_back(make_pair(I、J)); それ以外の 場合は(CH == ' M ' )man.push_back(make_pair(I、J)); } } int型の CNT = hou.size()。 V = 2 * CNT + 2 。 INT S = 2 * CNT、T = 2 * CNT + 1 。 以下のための(int型 I = 0 ; iはVを<+10 ; I ++ )G [i]が.clear(); 以下のために(int型 i = 0 ; iはCNT <I ++は{) のための(int型 J = 0 ; J <CNT; J ++ ){ addedge(I、CNT + J、1、ABS(男[I] 1次回- HOU [J ] 1次回)+ ABS(男性[I] .second - HOU [J] .second))。 } } のために(int型 i = 0 ; iは、CNTを<; iは++ ){ addedgeを(S、I、1、0 ); addedge(CNT + I、T、1、0 ); } のprintf(" %d個の\ n " 、min_cost_flow(S、T))。 } 戻り 0 。 }