トピック:https://vjudge.net/contest/307753#problem/G
質問の意味:木はあなたがパスの総数を見つけることができますし、パスの数の3%
アイデア:点線の洪水の問題
#include <cstdioを> する#include <CStringの> する#include <cmath> の#include <アルゴリズム> の#include <iostreamの> する#include <ベクトル> の#include <キュー> の#define MAXN 100005 の#define 0x3f3f3f3f MOD 使用して 名前空間STD; typedefのロング ロング; LL DA LL、 ベクトル <ペア<-1,11,11- >> MP [MAXN]、XXは[MAXN]; // 十分図保存 ; LL E [MAXN] BOOL VIS [MAXN]; // タグを用いた重力 LLをMAXSIZE [MAXN]、DIS [MAXN]、フラグにD [MAXN]、[MAXN]; // 現在のノードのMAXSIZE最大サブツリー SIZ LL [MAXN]、XDは[MAXN]; // 重力D距離の中心までDIS距離が現われ 、LLのN-、M、K、RT、SUM、QE、QE2、ANS1、ANS2 // SIZ現在のノードのサブツリーE RTは、現在のフォーカスの数から明らか ボイド {検索(XのLL、LL F)// 重心見つける = SIZ [X]を1 ; MAXSIZE [X] = 0 ; のために(INT I = 0 ;私はMPを[< X] .size(); Iは++ ){ 対 <LL、LL> Q = MP [X] [I]; IF(q.first == F || VIS [q.first])続行 ; // VIS配列タグ我々は重力を使用している (q.first、X)検索、 SIZを[X] + = SIZ [q.first]と、 MAXSIZE [X] = MAX(MAXSIZE [X]、SIZ [q.first]); } MAXSIZE [X] = MAX(MAXSIZE [X]、SUM-SIZ [X]); // ノードの総数マイナス現在のサブツリーの数=現在のノードは、父親のアイデア番号ツリーのルートである IF(MAXSIZE [X] < MAXSIZE [RT]){ RT = X; } } ボイドクエリ(LLのZ、LL SM){ IF(Z> ANS1){ ANS1 = Z; ANS2 = SM; } そう IF(Z == ANS1){ ANS2 + = SM; } } ボイドget_dis(X LL、F LL、LL LEN){ IF(LEN% 3。== 0)ANS1 ++ ; ANS2 ++ ; ANS1 + =フラグ[(3 -len%3 + 3)%3 ]。 ANS2 + =フラグ[ 0 ] +フラグ[ 1 ] +フラグ[ 2 ]。 E [lenの%3 ] ++ ; 以下のために(int型 i = 0 ; iは融点を<[X] .size(); iは++ ){ 対 <-1,11,11-> Q = MP [X] [I]; もし(q.first == F || VIS [q.first])続けます。 // DIS [q.first] =(DIS [X] + LEN)%3。 get_dis(q.first、X、(LEN + q.second)%3 )。 } } ボイド分割(LLのX){ VIS [X] = 1 。 // のprintf( "RT =%LLD ANS1 =%LLD ANS2 =%LLD \ n"、X、ANS1、ANS2)。 以下のために(int型 i = 0 ; iは融点を<[X] .size(); iは++ ){ 対 <-1,11,11-> Q = MP [X] [I]; もし(VIS [q.first])続けます。 // DIS [X] = q.second。 get_dis(q.first、X、q.second%3 )。 用(INT J = 0 ; J < 3; J ++ ){ フラグ[J] + = E [J]。 E [J] = 0 ; } } のために(int型 i = 0 ; iは< 3 ; iは++ ){ フラグ[I] = 0 ; } のために(int型 i = 0 ; iは融点を<[X] .size(); iは++ ){ 対 <-1,11,11-> Q = MP [X] [I]; もし(VIS [q.first])続けます。 // (ダ> 0)ブレークであれば、 合計= SIZ [q.first]。 RT = 0 ; MAXSIZE [RT] = MOD。 (q.first、X)を求めます。 分割(RT)。 } // VIS [X] = 0; } ボイドのinit(){ ANS1 = 0 ; ANS2 = 0 。 以下のために(int型私= 0 ; iが<= N; iが++ )MP [I] .clear(); 以下のために(int型 i = 0 ; iが<= N; iは++)VISを[I] = 0 ; 以下のために(int型 i = 0 ; iは< 3 ; iは++)フラグ[I] = 0 ; } int型のmain(){ LLのT; 一方、(scanf関数(" %のLLD "!、&N)= {EOF) LL、B、C。 その中に(); 以下のために(int型私= 1 ; I <= N- 1 ; iが++ ){ scanf関数(" %LLD%LLD%LLD "、&、&B、&C)。 MP [A] .push_back(make_pair(B、C))。 MP [B] .push_back(make_pair(c)参照)。 } 和 = N。// 当前节点数 RT = 0 ; [MAXSIZE 0 ] = MOD。// 置初值 見つける( 1、0 ); 分割(RT)。 ANS1 * = 2 ; ANS2 * = 2 ; ANS1 + = N。 ANS2 + = N。 W LL = __gcd(ANS1、ANS2)。 // のprintf( "%LLD /%LLD \ n"は、ANS1、ANS2)。 printf(" %LLD /%LLD \ n "、ANS1 / W、ANS2 / W) } }