トピックリンク:https://vjudge.net/problem/POJ-2516
アイデア:各良いラン最小コスト最大フローについては、ビルド一緒にチャートの実行にすべての商品と人々は、大きさのO(V ^ 2 * m)の大きすぎる、時間外の場合。
商品の在庫はinとout、制限的な役割を果たし、用品店とのスプリットポイントです。
ソース - >産品の需要の人々 - >株式が入る - 指摘する>インベントリ - >ミーティングポイント
INF側との間のモノの流れの源と人、人と人との人間フローの需要側。
ソースと手数料の人間の側面、費用0向こう側。
書式#include <iostreamの> の#include <cstdioを> する#include <アルゴリズム> 書式#include <CStringの> の#include <キュー> 使用して 名前空間をSTD。 CONST INT N = 60、INF =(INT )1E9。 整数N、M、K、TOT。 int型のヘッド[N << 2 ]、あらかじめ[N << 2 ]、D [N << 2 ]、VIS [N << 2 ]。 INT P [N] [N]、G [N] [N]、C [N] [N] [N]。 構造体ノード{ int型、NXT、キャップ、流れ、コストに、 } E [N * N]。 インライン無効追加(INT U、INT V、int型のキャップ、INT流れ、INT コスト){ E [TOT] .TO = V。E [TOT]の.cap =キャップ。E [TOT] .flow = 流れます。 E [TOT] .cost =コスト。E [TOT] .nxt =頭部[U]。ヘッド[U] = TOT ++ 。 E [TOT] .TO = U。E [TOT]の.cap = 0。E [TOT] .flow = 流れます。 E [TOT] .cost = -COST。E [TOT] .nxt =頭部[V]。ヘッド[V] = TOT ++ 。 } ボイド入力(INT&sum_need){ sum_need = 0 。 以下のための(int型 I =1 ; I <= N。++ I){ ため(INT J = 1 ; J <= K; ++ J){ scanf関数(" %のD "、&P [I] [J])。 sum_need + = P [I] [J]。 } } のために(INT iは= 1 ; I <= M; ++ I){ ため(INT J = 1 ; J <= K; ++ j)は scanf関数(" %のD "、&G [I] [J] ); } のための(INT O =。1 ; 0 <= K; ++ O){ ため(INT I = 1 ; I <= N; ++ I){ ため(INT J = 1。 ; J <= M; ++ J) scanfの(" %のD 「&C [O] [I]、[J]); } } } ボイド build_map(INT O、INT S、INT T){ // 0 1〜n個のヒトソースN + 1〜N + Mストックエンター、 // N-M + 1〜+ N-M + 2 *在庫ポイントN + 2 * M + 1シンク。 以下のための(int型 I = 1 ; I <= N-; ++I){ ため(INT J = 1 ; J <= M; ++ J){ 追加(I、J + N、INF、0 、C [O] [I] [J])。 } } のために(INT iは= 1 ; I <= N; ++ I){ 追加(S、I、P [I] [O]、0、0 ); } ため(INT iは= 1 ; I <= M; ++ I){ 追加(I + N、I + N + M、G [i]は、[O]、0、0 ); 追加(I + N + M、T、INF、0、0 ); } } ブール spfa(INT S、INT T){ ため(INT I = S; I <= T; ++ I){ D [i]は = INF。プレ[I] = - 1。VIS [i]を= 偽; } キュー < int型 > QUE。 que.push(S)。D [S] = 0 ; VIS [S] = 真。 しばらく(!que.empty()){ int型になりました= que.front(); que.pop(); VIS [今] = 偽; 以下のための( int型 O =頭部[今]。〜O; O = E [O] .nxt){ int型へ= E [O] .TO。 もし(E [O]の.cap> E [O] .flow && D [に対する]> D [今] + E [O] .cost){ [に対する] D = D [今] + E [O] .cost ; 【に】予め = O。 もし(!VIS [へ]){ VIS [へ] = 真; (へ)que.push。 } } } } もし(予備[T] == - 1)戻り 偽。 そうしないと リターン 真; } INT MCMF(INT S、INT T、INT&MF){ int型ミン= INF、MC = 0 。 一方、(spfa(S、T)){ 最小 = INF。 用(INT O =プレ[T];〜O、O =事前[E [O ^ 1 ] .TO]){ 最小 =最小(最小、E [O]の.cap - E [O] .flow)。 } のための(INT O =プレ[T];〜O、O =プレ[E [O ^ 1 ] .TO]){ E [O] .flow + = 分; E [O^ 1 ] .flow - = 分; } MF + = 分; MC + = D [T] * 分; } 戻りMC。 } ボイドinit_main(){ memsetの(p、0、はsizeof (P))。 memsetの(G、0、はsizeof (G))。 memset(C、0、はsizeof (c)参照)。 } int型のmain(){ int型、S、T、MC、MF、sum_need。// 商品总需求量 ながら(〜のscanf(" %D%D%D "、&N、&M、及びk)&&(N + M + K)){ init_main(); 入力(sum_need)。 S = 0。T = N + 2 * M + 1 。 MC = MF = 0 。 用(INT O = 1 {++ O; 0 <= K)// 第O种商品 のための(INT I = S; I <= T; ++ I)ヘッド[I] = - 1。TOT = 0 ; build_map(O、S、T)。 MC + = MCMF(S、T、MF)。 } // もし(MF == sum_need)のprintf( "-------------%D \ n"、MC)。 //他のprintf( "--------------なし\ N"); もし(MF == sum_need)のprintf(" %dの\ n " 、MC)。 他のprintf(" -1 \ N " ); } 戻り 0 。 }