【パレード] BZOJ3691

フェイス質問

http://darkbzoj.tk/problem/3691

問題の解決策

非常に多くのお問い合わせを見て、それは確かに私たちは高いのがなければならないかを知る、チャートの実行を再構築することはできません。

まず、それは、後に転送要求$ $ Floyedの閉鎖を繰り返してもよいです。

試合は取り除くことができ、時には試合を取り除くが、$ Cは$より大きく取得するとあなたは、$の+のC $を飢え番目の$ n $と$ X $学部二部グラフに想像することができ、そうではありません掘り出し物。

したがって、最小コスト最大流量は、$ DIS [T] $(特定のインクリメント)の間に記録されたときに上半分で直接に検索クエリ。

#include <地図> 
の#include <スタック> 
の#include <キュー> 
の#include <ベクトル> 
の#include <cstdioを> 
する#include <CStringの> 
する#include <iostreamの> 
する#include <アルゴリズム>
 の#define N千
 の#define S 0
 の#define T(2 * N + 1)
 の#defineは長い長いLL
 の#define INTレジスタRI
 の#define INF十億七
 使用 名前空間STDを、

INTのN、M、K、C-C、Q。
INT DIS [N] [N]。
LLのTOT [N]。
INT CAI [N]、ウェイ[N]。

構造体のグラフ{
  ベクター< 整数 > 、に、C、W。
  ベクター < INT > ED [N]。
  LL DIS [N]。INTのCUR [N]。
  BOOL VIS [N]。
  ボイド add_edge(int型int型 B、int型 AW、int型AC){ 
    to.push_back(B)。w.push_back(AW)。c.push_back(AC)。ED [A] .push_back(to.size() - 1 )。
    to.push_back(A)。w.push_back(0)。c.push_back(-ac)。ED [B] .push_back(to.size() - 1 )。
  } 
  BOOL spfa(){ 
    memsetの(DIS、0x3fをはsizeof(DIS))。
    memsetの(VIS、0はsizeof (VIS))。
    キュー < 整数 > Q; 
    DIS [S] = 0 ; q.push(S); VIS [S] = 1 一方、(!q.empty()){
       int型のx = q.front()。q.pop();
      (RI i = 0 ; iが編<[X] .size(); iは++ ){
         int型、E = ED [X] [I];
        もし(DIS [乃至[E]]> DIS [X] + C [E] && W [E]){ 
          DIS [[E]に] = DIS [X] + C [E]。
          もし(!VIS [] E [へ])VIS = [E] [へ]1 、q.push([E]に)。
        } 
      } 
      VIS [X] = 0 
    } 
    戻り DIS [T] < INFします。
  } 
  INT DFS(int型のx、int型LIM){
     場合(X == T || LIM!)戻りLIM。
    LLの合計 = 0 ; VIS [X] = 1 (RI&I = CUR [X]; iは<ED [X] .size(); iは++ ){
       int型、E = ED [X] [I];
      もし(DIS [X] + C [E] == DIS && W [E] [E] [する] &&!VIS [] E [に対して]){
         int型、F = DFS(LIM(分、[E]に我々]));
        W [E] - = F。[ワット1 ^ E] + = F。
        LIM - = F。和+ = F。
        もし(!LIM)のリターン合計。
      } 
    } 
    戻り値の和。
  } 
  ボイドzkw(){ 
    LLのRET = 0 
    CC = 0 一方、(spfa()){ 
      memsetの(VIS、0はsizeof (VIS))。
      memset(CUR、0はsizeof (CUR))。
      INT F =のDFS(S、INF)。
      RET + = F * DIS [T]。
      ++ CC; CAI [CC] = DIS [T]。TOT [CC] RETを=。ウェイ[CC] =ウェイ[CC- 1 ] + F。
    } 
  } 
} G。

INT {main()の
   int型、B、L。
  scanf関数(" %D%D%D "、&​​N、&M、およびK); 
  memset(DIS、0x3fをはsizeof (DIS))。
  以下のために(RI i = 1 ; iが<= N; iが++)DIS [i]は[I] = 0 (RI i = 1 ; I <= M; iは++ ){ 
    scanf関数(" %D%D%D "、&​​、&B、&L)。
    DIS [A] [B] = 分(DIS [A] [B]、L)。
  }
  (RI KK = 1 ; KK <= N; KK ++ のための(RI iは= 1 ; iが<= N; I ++ のための(RI J = 1 ; J <= N; J ++)DIS [I] [J] =分(DIS [I]、[J]、DIS [I] [KK] + DIS [KK] [J])。
  (RI i = 1 ; I <= n iは++ のために(RI J = 1 ; J <= N; J ++)場合(!私は= j)はG.add_edge(I、N + J、1 、DIS [I ] [J])。
  (RI I = 1 G.add_edge(S、I、; iが<= N I ++)は10 );
  (RI I = N + 1 ; iは= < 2 * N; iは++)G.add_edge(I、T、10 ); 
  ウェイ[ 0 ] = 0 ; 
  G.zkw(); 
  (RI i = 1 ; iは= Kを<I ++は{)
    のscanf(" %dの"、&Q)。
    INT X = LOWER_BOUND(CAI + 1、CAI + CC + 1、Q) - CAI。
    X - ; 
    printf(" %LLDする\ n "、(N-ウェイ[X])* 1LL * Q + TOT [X])。
  } 
}

 

おすすめ

転載: www.cnblogs.com/shxnb666/p/11297046.html