フェイス質問
https://www.luogu.org/problem/CF555E
問題の解決策
#include <cstdioを> する#include <iostreamの> する#include <ベクトル> の#include <アルゴリズム> の#include <CStringの> 使用して名前空間STD。構造体スタック{ INT [ 200050 ]、尾; ブール B [ 200050 ]。 ボイドクリア(){memsetの(0、はsizeof(a)参照)。memset(B、0、はsizeof(b)参照)。尾= 0 ;} ボイドプッシュ(INT X){++尾; [尾] = xと; B [X] = 真;} int型の上部(){ 戻り[テール];} ボイドポップ(){B [尾部]] = 偽。tail-- ;} BOOL ISIN(INT X){ 戻りB [X];} } STK。 INTの N、M、Q、DFN [ 200050 ]、低[ 200050 ]、cloct = 0 。 INTベル[ 200050 ]、CNT = 0 。 INT S [ 200050 ]、T [ 200050 ]。 ベクター < INT >に[ 200050 ]、ID [ 200050 ]。 ベクトル < 整数 >について[ 200050]; INT [F 200050 ] [ 25 ]、D [ 200050 ]。 int型 F1 [ 200050 ]、F2 [ 200050 ]。 BOOL ANS; ボイド tarjan(INT今、int型faid){ 低い[今] =のDFN [今] = ++ cloct。 stk.push(今)。 int型 I、L = [今] .size()に、 用(i = 0 ; iはL <; iは++)場合(!ID [今] [I] = faid){ 場合(!DFN [乃至[今] [I]]){ tarjan(の[今] [I] 、ID [今] [I])。 低[今] =([今] [I]に]、[今低低い)分。 } 他{ 場合(stk.isin(の[今] [I])){ 低い[今] = 分(低[今]、DFN [に対して[今] [I])。 } } } もし(低[今] == DFN [今]){ int型のX; ++ CNT; 実行{ X = stk.top()。 ベル[X] = CNT。 stk.pop(); } 一方(X =!今)。 } } 無効 maketree(int型今、int型 FA、int型を深い){ int型 I、L = 約[今] .size()。 F [今] [ 0 ] = FA。 用(i = 1 ; iは<= 19 ; iは++)F [今] [I] = F [F [今] [I- 1 ]] [I- 1 ]。 D [今] = 深いです。 用(i = 0 ; iはL <; iは++)場合(!についての今] [I] = FA)maketree(約[今] [i]は、今、深い+ 1 )。 } ボイドワーク(INT U、INT V){ F1 [U] + = 1 ; F1 [V] - = 1 ; F2 [U] + = 1; F2 [V] + = 1 ; もし(D [U] < D [V])スワップ(U、V)。 int型Iを、LCA; 以下のために(私= 19 ; I> = 0 ; i--)場合(D [F [U] [I]]> = D [V])U = F [U] [I]。 もし(U == V)LCA = U。 他{ ための(I = 19 ; I> = 0 ; i--)であれば(F [U] [I] = F [v] [I]!)U = [U] [i]は、V = F のF [ V] [i]は、 LCA = F [U] [ 0 ]。 } F2 [LCA] - = 2 。 } 無効 treesum(int型になりました、INT FA){ int型 I、L = 約[今] .size()。 用(i = 0 ; iはL <; iは++)場合(約[今] [I] =!FA){ treesum([今]について[I]、今)。 F1 [今] + = F1 [i]は[]になりました[に関する]; F2 [今] + = F2 [i]は[]になりました[に関する]; } もし(ABS(F1 [今])= ABS(F2 [今])!)ANS = 偽; } int型のmain(){ int型 I、U、V、から、TO0。 scanf関数(" %D%D%D "、&N、&M&Q)。 用(i = 1 ; I <= M、I ++){ scanf関数(" %d個の%d個"、&U&V); S [i]は = U。T [I] = V。 [U] .push_back(V)へ。ID [U] .push_back(I)。 [V] .push_backに(U)。ID [V] .push_back(I)。 } stk.clear()。 用(i = 1 ; iが<= N; iは++)場合 tarjan(I、 - ([I] DFN!)1 )。 用(i = 1 ; iが<= M; iは++ ){ 場合(!ベル[S [I] = ベル[T [I]]){ 約[ベル[S [i]は]一back(ベル[T [私]]); 約[ベル[T [I]]]一back(ベル[S [I])。 } } のための(I = 1;私は= CNTを<; iは++)場合(F [i]が[!0 ])maketree(I、I、1 )。 ANS = 真; 用(i = 1 ; iが<= Q; iは++ ){ scanf関数(" %d個の%のD "、&から、&TO0)。 // のprintf( "%D%D \ n"は、ベルベル[TO0]、[から])。 // のprintf( "%D%D \ n"は、F [ベル[]から] [19]、F [ベル[] TO0] [19])。 もし(F [ベル[ から ] [ 19 ] = F [ベル[TO0] [!19 ]){ANS = 偽。引き続き;} 場合([BEL から!] =ベル[TO0])(ベル[動作から】ベル[TO0、])。 // ヴァル[から] = 1; ヴァル= [に対して] - 1。 } // (i = 1; iが<= N; iが++)のためCOUT <<ベル[I] <<」「。 treesum(1 - 1 )。 もし(ANS)プット(" はい")。他のプット(「ノー」)。 }