質問の意味:
彼らは商品を調達する必要がある事業、商品のサプライヤーのNの数、ならびに項目を必要とする企業のM、N Kの種類があり、各項目は、対応する要求を有し、M企業は、各アイテムの在庫を対応され、その後でK N * Mの行列は、ビジネスユニットへの供給業者からKの物品搬送の価格を表し、それが最小コストの標準最大流量である、我々はすべてのサプライヤーとソースのために、そのような側面を作成する必要がありますストリームのサイズを確立するためのポイントはサイドが所有する数であり、インフィニティエッジ及び単価の側面を確立するためのビジネスマンは、ストリームの価格です、そして、そのニーズの大きさを確立するためのミーティングポイントに到達するために、ビジネス側の流れから始まり、ミーティングポイントソース側を確立するためのコストは0です。
アイデア:
最初は、私が直接費用流を実行する予定が、この実行後、あなたがそれを完了するために再度指示したいならば、Nは、考慮ビジネスのニーズだけでなく、M・プロバイダーが取っている、ポイントTを見つけるだろう議論するためにK回に分けた場合の数があまりにも多く、このような点を(N + M + N * K + M * K)の数であるが、我々はそれを変更することができ、時間の複雑さをダウン最適化することはできません。
そこで、次のように商品の種類及び建設側のコストに対応する各プロセスは、ストリームを実行し、K回に分けます。
#include <iostreamの> する#include <cstdioを> する#include <cmath> の#include < ストリング > の#include <CStringの> する#include <アルゴリズム> の#include <限界> の#include <ベクトル> の#include <スタック> の#include <キュー> #include < セット > の#include <地図> の#define lowbit(X)(X&( - X)) の#define PI 3.141592653589793 の#define E 2.718281828459045 の#define INF 0x3f3f3f3f の#define半分(L + R)>> 1つの#defineLSNのRT << 1 の#define RSN RT << 1 | 1 の#define LSONのLSN、L、ミッド の#define RsonのRSN、ミッド+ 1、R用 の#define QL LSON、QL、QR の#define QR Rson、QL、QR の#define私自身、室温、L、R 使って 名前空間はstdを、 const int型 MAXN = 107、S = 0 ; 整数 N、M、K、T、必要[ 55 ]いる[ 55 ]、ショップ[ 55 ] [ 55 ]、優れた[ 55 ] [ 55 ]、R [MAXN] [MAXN]、[MAXN] [MAXN] C ; INT プレ[MAXN]、DIST [MAXN]、フロー[MAXN]、ANS。 キュー < 整数 > Q; BOOL inque [MAXN]。 ブールspfa() { memsetの(前、0、はsizeof(PRE))。memset(DIST、INF、はsizeof(DIST))。memsetの(inque、偽、はsizeof (inque)); Q.push(S)。inque [S] = 真。DIST [S] = 0 ; フロー[S] = INF。 しばらく(!Q.empty()) { int型のu = Q.front(); inque [U] = 偽。Q.pop(); 以下のために(int型 I = 0 I <= T;;私は++) { もし(R [U] [I] && DIST [I]> DIST [U] + C [U] [I]) { DIST [I] = DIST [U] + C [U] [I]。 フロー[I] = 分(フロー[U]、R [U] [I])。 事前[I] = U。 もし(!inque [I]) { inque [I] = 真。 Q.push(I); } } } } 戻りプレ[T]を。 } INT EK() { int型 ANS = 0; 一方、。(spfa()) { int型今= T、ラス= プレ[今]。 一方、(今) { R [ラス] [今] - = 流量[T]。 R [今] [ラス] + = 流量[T]。 今 = ラス。 ラス = あらかじめ[今]。 } ANS + =流量[T] * DIST [T]。 } 戻りANS。 } インラインボイドのinit() { ANS = 0。T = N + M + 1 のmemset(必要、0、sizeof (ニーズ)); memsetを(有し0、はsizeofを)(ました)。 } int型のmain() { 一方(scanf関数(" %D%D%D "、&N、&M、&K)&&(N || M || K)) { INIT()。 用(int型 iは= 1 ; iが<= N; iが++ ) { ため(INT J = 1 ; J <= K; J ++ ) { scanf関数(" %のD "、およびショップ[I] [J ];買物[I] [J])。 必要[J] + = } } のために(int型 I = 1 ; I <= M; iは++ ) { ための(int型 J = 1 ; J <= K; J ++ ) { scanf関数(" %のD "、および良好な[I] [J])。 持っている[J] + = 良い[I] [J]。 } } ブールフラグ= 真。 以下のために(int型 i = 1 ; iが<= Kを、iは++ ) { 場合(必要[I]> いる[i])と { フラグ = 偽。 破ります; } } のための(int型 i = 1 ; iが= Kを<Iは++ ) { memsetの(R、0、はsizeof (登録商標)); memset(C、0、はsizeof (c)参照)。 用(INT J = 1 ; J <= N; J ++ ) { R [S] [J] = ショップ[J] [I]; 以下のための(int型 KK =1 ; KK <= M。KK ++ ) { scanf関数(" %のD "、&C [J] [N + KK])。 C [N + KK] [J] = -c [J] [N + (株)]。 R [J] [N + KK] = INF。 } } 場合(フラグが!)続けます。 用(INT J = 1 ; J <= M; J ++)R [N + J] [T]は= 良い[j]を[I]。 ANS + = EK()。 } もし(!フラグ){のprintf(" -1の\ n ");続け; } のprintf(" %d個の\ n " 、ANS)。 } 戻り 0 。 }