問題の意味:無向グラフが与えられると、アリスは、点Aのセットから選択され、ボブはCXKは、コーパス内のポイントを選択し、B点のセットから選択されます。次に、「コレクションのポイントの最短距離に3を」期待をお願いします。
考える:裸のタイトルは、3つのポジションを考えると、どこで設定された最小価格から行くように頼まれました。その質問は、あなたが答えを更新することができ、三点走行3回SPFAです。そして、この質問はCxkは、非常に厄介な、しかし、右側が1で、Tmは直接、まだそれを拡張BFSされていないことを指摘しています。次いでDIS [i]の列挙位置アリスとボブは、DISA [I = ] + DISB [j]を、 その後、拡張することができます。問題となる可能性がログでこれをオーバーしないように注意してください。
<ビット/ STDC ++ H>の#include の#defineは長い長いっ の#define REPは(iは、、B)のための式(I ++; iが= Bを<Iは= INT) 使用して 名前空間STDを、 const int型 MAXN = 200010 ; const int型 INF = 1E9; INT DISA [ 21 ] [MAXN]、DISB [ 21 ] [MAXN]、[MAXN]、B [MAXN]。 INT Laxt [MAXN]、次に[MAXN]に[MAXN]、CNT、N。LLの合計。 ボイド追加(INT U、INT V) { 次に[ ++ CNT] = Laxt [U]。Laxt [U] = CNT。[CNT] =にV。 } ボイド BFS(INT DIS []、INT ST) { 担当者(I、1、N)DIS [I] = INF。DIS [ST]は= 0 。 キュー < 整数 > Q; q.push(ST); しばらく(!q.empty()){ int型のu = q.front(); q.pop(); 用(int型 ; I = I iは= Laxt [U] {次に[I]) であれば(== [[I]へ] DIS {INF) [I]へ] DIS = DIS [U] + 1 。 q.push(TO [I])。 } } } } int型NUM [MAXN]、[MAXN] C、[MAXN] DIS。 空隙)(解決// 基数排序+两个单调队列 { 担当者(I、0、N + N)NUM [I] = 0 ; 担当者(I、0、N)NUM [DIS [I] ++、D [I] = 0 ; 担当者(I、1、N + N)NUM [I] + = NUM [I- 1 ]。 担当者(I、1 C、N)[NUM [DIS [I]] - ] = I。 キュー < 整数 > Q1、Q2; 担当者(I、1 、N)q1.push(C [I])。 一方、(!q1.empty()||!q2.empty()){ 場合(q2.empty()||(!q1.empty()&&!q2.empty()&& DIS [q1.front()] < DIS [q2.front()])){ int型、U =q1.front(); q1.pop(); 用(int型 ; I I = iは= Laxt [U] {次に[I]) であれば(> DIS [U] + [I]へ] DIS 1 {) DIS [に[I] = DIS [U] + 1 。 q2.push(TO [I])。 } } } 他{ int型、U = q2.front()。q2.pop(); 用(int型 ; I I = iは= Laxt [U] {次に[I]) であれば(> DIS [U] + [I]へ] DIS 1 {) DIS [に[I] = DIS [U] + 1; q2.push(TO [I])。 } } } } 担当者(I、1、N)の和+ = DIS [i]は、 } int型のmain() { int型 C = 0 、T、M、A、B、U、V。 scanf関数(" %のD "、&T)。 一方、(T-- ){ scanf関数(" %d個の%のD "、&N、&M)。 担当者(I、1、N)Laxt [I] = 0 ; CNT = 0 ; 担当者(I、1 、M){ scanf関数(" %d個の%d個"、&U&V); (V、U)を追加します。(V、U)を追加。 } のscanf(" %dの"、&A)。担当者(I、1、A)のscanf(" %dの"、および[I])。 scanf関数(" %のD "、&B)。担当者(I、1、B)のscanf(" %dの"、&B [I])。 担当者(I、1 、A)BFS(DISA [I]、[I])。 担当者(I、1 、B)BFS(DISB [I]、B [I])。 合計 = 0 ; 担当者(I、、1 、B){ 担当者(K、1、N)DIS [k]はDISA [I] [K] + = DISB [j] [k]を、 解決する(); } LL ANS = 1LL * A * B * N。 LL G = __gcd(ANS、合計)。 printf(" ケース#%dの:"、++ C); もし(G ==和)のprintf(" %LLDする\ n "、和/ G) 他のprintf(" %LLD /%LLD \ n "、和/ gで、ANS / G) } 戻り 0 。 }