特別なトピック11 kuangbinネットワークは、最小のコストPOJを流し - 2516

トピックリンク: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 = 0E [TOT] .flow = 流れます。
    E [TOT] .cost = -COST。E [TOT] .nxt =頭部[V]。ヘッド[V] = TOT ++ 
} 

ボイド入力(INTsum_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]、00 ); 
    } 
    ためINT iは= 1 ; I <= M; ++ I){ 
        追加(I + N、I + N + M、G [i]は、[O]、00 ); 
        追加(I + N + M、T、INF、00 );
    } 
} 

ブール spfa(INT S、INT T){
     ためINT I = S; I <= T; ++ I){ 
        D [i]は = INF。プレ[I] = - 1VIS [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、INTMF){ 

    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 = 0T = N + 2 * M + 1 
        MC = MF = 0 INT O = 1 {++ O; 0 <= K)// 第O种商品
            のためのINT I = S; I <= T; ++ I)ヘッド[I] = - 1TOT = 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 
}

 

おすすめ

転載: www.cnblogs.com/SSummerZzz/p/12258875.html