[]最短BZOJ2125

フェイス質問

http://darkbzoj.tk/problem/2125

問題の解決策

#include <cstdioを> 
する#include <CStringの> 
する#include <iostreamの> 
する#include <ベクトル> 
の#include <cstdlib> 
の#include <スタック>
 の#define RI登録INT
 の#define N 50500
 の#define M 105000
 使用して 名前空間STDを、

int型TN、N、M、Q。

インラインint型リード(){
   int型 RET = 0、F = 0チャー CH = GETCHAR()。
  一方、(CH < ' 0 ' || CH> ' 9 '' - ')、CH = GETCHAR()。
  一方、(CH> = ' 0 ' && CH <= ' 9 ')RET * = 10、RET + = CH- ' 0 '、CH = GETCHAR()。
  リターン F - ?RET:RET; 
} 

int型ciren [N]を。
BOOL 鄭[N]。

構造体ツリー{ 
  ベクトル < 整数 >に[N << 1 ]、LEN [N << 1 ]。
  ボイド add_edge(INT U、INT V、INT W){
    [V] .push_backに(U)。LEN [V] .push_back(W)。
  } 
  INT FA [N << 1 ]、F [N << 1 ] [ 19 ]、D [N << 1 ]。
  INTのsL [N << 1 ]。
  ボイド maketree(int型のx、int型FF){ 
    F [X] [ 0 ] = FA [X] =のFF。
    (RI i = 1 ; iは= < 18 ; iは++)F [X] [I] = F [F [x]は[I- 1 ]] [I- 1 ]。
    (RI i = 0 ; iが<[X] .size(); iは++ ){
       int型、Y = に[X] [I]; 
      のsL [Y]=のsL [X] + LEN [X] [I]; D [Y] = D [X] + 1 
      maketree(Y、X)。
    } 
  } 
  int型 LCA(int型のx、int型のY){
     場合(D [X] < D [Y])スワップ(X、Y)
    (RI I = 18 ; I> = 0 ; i--)場合(D [F [X] [I]]> = D [Y])X = F [X] [I]。
    もし(x == y)は戻りX。
    (RI I = 18 ; I> = 0 ; i--)であれば(![X] [I] = F [Y] F [i])と、X = F [X] [i]は、Y = F [Y ][私];
    戻りFAを[X]。
  } 
  int型の int型ジャンプ(X、int型のY){
     ため(RI I = 18 ; I> = 0 ; i--)場合(D [F [X] [I]]> D [Y])X = F [x]は[I ];
    リターンのx; 
  } 
  int型の照会(int型のx、int型のY){
     int型、T = LCA(X、Y)
    もし(T> TN){
       int型 X0 = ジャンプ(X、T)。
      INT Y0 = ジャンプ(Y、T)。
      INT ANS =のsL [X] -sl [X0] +のsL [Y] - のsL [Y0]。
      もし(鄭[X0] =!鄭[Y0]){ 
        ANS + =分(SL [X0] +のsL [Y0] -2 *のsL [T]、ciren [T] -sl [X0] -sl [Y0] + 2 * のsL [T])。
      } 
      { 
        ANS + =分(ABS(SL [X0] -sl [Y0])、ciren [T] -abs(SL [X0] - のsL [Y0]))。
      } 
      戻りANS。
    } 
    そう リターン SLが[X] +のsL [Y] - 2 * のsL [T]。
  } 
} T。

構造体グラフ{ 
  ベクトル < INT > [N]に、LEN [N]。
  INT DFN [N]、低[N]、DR [N]。
  int型のCNT; 
  スタック < int型 > S;
  無効 add_edge(int型U、int型 V、INT W){ 
    に[U] .push_back(V)。LEN [U]は.push_back(W)。
    [V] .push_backに(U)。LEN [V] .push_back(W)。
  } 
  ボイド tarjan(int型X){ 
    DFN [X] =低[X] = ++ CNT。
    s.push(X)。
    (RI i = 0 ; iが<[X] .size(); iは++ ){
       int型、Y = に[X] [I];
      もし([Y] DFN){ 
        低い[X] = 分(DFN [Y]、[x]は低いです)。
      } 
      { 
        DR [Y] = DR [X] + LEN [X] [I]; 
        tarjan(Y)。
        もし(低[Y]> =DFN [X]){
           ++ N。
          INT T = s.top()、cirl = DR [T] - DR [X]。
          (RIをJ = 0 ; J <に[T] .size(); J ++)場合(に[T] [J] == X){cirl + = LEN [T] [J]。ブレーク;} 
          ciren [N] = cirl。
          実行{ 
            T = s.top()。s.pop();
            もし(DR [T] -dr [X]> cirl-DR [T] + DR [X])鄭[T] = 1 
            T.add_edge(T、N、分(DR [T] -dr [x]は、cirl-DR [T] + DR [X])); 
          } 
          一方、(T =!Y)。
          T.add_edge(N、X、0); 
        } 
        低[X] = 分(低[x]は、低[Y])。
      } 
    } 
  } 
} G。

INT のmain(){
   int型、U、V、W。
  TN = N =(読み取り)M =読み取ります(); Q = 読み取り();
  (RI i = 1 ; I <= M iは++ ){ 
    U =を読み取ります()。V =)(読み取ります。W = 読み取り(); 
    G.add_edge(U、V、W)。
  } 
  G.cnt = 0G.dr [ 1 ] = 0G.tarjan(1 )。
  T.maketree(11 )。
  (RI I = 1; I <= Q; iが++ ){
     int型、U =読み取る()、V = 読み取ります(); 
    printf(" %d個の\ n " 、T.query(U、V))。
  } 
  戻り 0 
}

 

おすすめ

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