まだDFS-new_bzoj Sta

タイトルリンク: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      forint i = 1 ; i <n; i ++ ){
 45          int x、y; scanf(" %d%d"&X&Y);
 46          追加(x、y)は、追加(Y、X);
 47      }
 48      DFS1(10); DFS2(10 );
 49      のprintf(" %D \ n " 、 no);
 50      return  0 ;
 51 }

 

おすすめ

転載: www.cnblogs.com/DZN2004/p/12686227.html