フェイス質問
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 = 0。G.dr [ 1 ] = 0。G.tarjan(1 )。 T.maketree(1、1 )。 用(RI I = 1; I <= Q; iが++ ){ int型、U =読み取る()、V = 読み取ります(); printf(" %d個の\ n " 、T.query(U、V))。 } 戻り 0 。 }