フェイス質問
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 ++)は1、0 ); 用(RI I = N + 1 ; iは= < 2 * N; iは++)G.add_edge(I、T、1、0 ); ウェイ[ 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])。 } }