タイトルリンク:https://vijos.org/d/newbzoj/p/590c9893d3d8a132109937a3
実際、意味は非常に単純です。最初に見てください。Nポイントのツリーを与え、ポイントを見つけます。このポイントをルートとするツリーの場合、すべてのポイントの深度の合計が最大です。
暴力的な場合は、TLEである必要があります。
だから私たちは方法を見つけなければなりません。
DFSのn倍からDFSの2倍に最適化した質問を1つ覚えています
この質問は大丈夫ですか?
それについて考えることができます。
答えはイエスです。
アイデアを見てみましょう:
最初に、すべてのポイントは親ツリーのポイント+子ツリーのポイントに等しくなります。
次に、2つの累積を要求します。
サブツリーの全体の深さは簡単に見つけることができます。つまり、息子の合計の深さを+サイズに追加するだけです。
親ツリーは前処理が必要なため、少し面倒です。2番目のディープサーチで解決されます。
ポイントの場合、このポイントの親ツリーは[父親+父親の親ツリー+兄弟の子ツリー]です。
次に、それらを個別に追加し
ます。式をプッシュするように注意してください。
時間の複雑さO(n)の
詳細はごくわずかです。
1.計算式を計算する必要があります(同じ項目を加算および減算し、それを除去しないでください...さもなければ調整できません...)
2.この質問には長い時間がかかります
背後にはコードがあります。
いくつかのメモを追加しました。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 const int maxn = 1000005 ; 6 名前空間std を使用 。 7 typedef long long ll; 8 int n、no、to [maxn << 1 ]、next [maxn << 1 ]、head [maxn]、cnt; 9 ll sum [maxn]、size [maxn]、fas [maxn]、ans; 10 void add(int x、int y){ 11 to [++ cnt] = y; next [cnt] = head [x]; head [x] = cnt; 12 } 13 void DFS1(int x、int pre){ 14 size [x] = 1 ; int i、y; // sizeはサブツリーのサイズで、x 15 for(i = head [x]; i ; i = next [i]){ 16 if((y = to [i])!= pre){ 17 DFS1(y、x); 18 size [x] + = size [y]; 19 sum [x] + = sum [y] + size [y]; // sumは深度の合計ですが、xは含まれません 20 } 21 } 22 } 23 void DFS2(int x、int pre){ 24 int i、y; 25 if(x!= 1)fas [x] = fas [pre] + n-size [pre] + sum [pre] -sum [x] -size [ x] + size [pre] -size [x] -1 + 1 ; 26 // fas [pre] + n-size [pre]は最初の部分です 27 // sum [pre] -sum [x] -size [x ] + size [pre] -size [x] -1は2番目の部分 28 // 1は3番目の部分 29 // 式はよく理解されている 30 if(ans <fas [x] + sum [x]){ // fasは親ツリーであり、 31 ans = fas [x] + sum [x]; 32 no = x; 33 } 34 else if(ans == fas [x] + sum [x])no = min(no、x); 35 for(i = head [x]; i; i = next [i]){ 36 if((y = to [i])!= pre){ 37 DFS2(y、x); 38 } 39 } 40 } 41 int main(){ 42 // freopen( "a.in"、 "r"、stdin); 43 scanf(" %d "、&n); 44 for(int i = 1 ; i <n; i ++ ){ 45 int x、y; scanf(" %d%d"&X&Y); 46 追加(x、y)は、追加(Y、X); 47 } 48 DFS1(1、0); DFS2(1、0 ); 49 のprintf(" %D \ n " 、 no); 50 return 0 ; 51 }