羅区[P2986]偉大な収集牛

説明

右側が、ポイントANSを得るようにしながら所定の大ツリーノードは、右ビット最小コスト、請求$コスト= \和\ limits_ {i = 1} ^ {n}は{ヴァル[I] * DIS(ANS、I)} $

溶液

木のDP

それでも二回DFSを通じて解決

核となるアイデアは、(用語はLYDから来ている「アルゴリズムコンテストステップアップガイド」)「ルート法をスキャンし、変更する第二」であります

我々は、DFSルートであり、DISを犠牲にして配置されたとき、最初のパスは、ANSが決定されると仮定する

TOT [j]はjが表す$ DIS [I] = \和の\ limits_ {息子にj個の\(I)} {DIS [J] + LEN(I、J)* TOT [J]} $は、明らかに存在しますノード点をルートと右サブツリー、および

だから我々は、「チェンジ・ルート」を達成するために、再度DFS

現在のノードを仮定iと、私は父が正しく計算されていた、我々は[FA] $ F $のように父親に位置価格ANSを覚えて、我々は、$ F [FA] $で[i]は$ F $を見つける方法を検討します

$ F二つの部分からなる[FA] $:ルートにするサブツリーと、残りのI配慮を。[FA] Fだから我々は最初の$ $ iはマイナスサブツリーのルートのコスト、そして私は、私費を行ってきました、プラス私のの残りの費用が来ることをルートとするサブツリーを追加

詳細な実装コードを参照してください。

時間の複雑さは$ O(n)は$です

コード

1つの#include <ビット/ STDC ++ H>
 2  使用して 名前空間STDを、
3 typedefの長い 長いLL。
4  のconst  int型 MAXN = 100010 5インラインint型リード(){
 6      INT RET = 0、OP = 1 7      チャー C = GETCHAR()。
8      ながら(!isdigit(c)参照){
 9          もし(C == ' - ')OP = - 1 10          のC =getchar関数();
11      }
 12      ながら(isdigit(C)){
 13          RET = RET * 10 + C - ' 0 ' 14          C = GETCHAR()。
15      }
 16      リターンのRET *のOP。
17  }
 18  構造体ノード{
 19      のint NXT、DIS、であり;
20 } [MAXN << 1 ]。
21  のint NUM、ヘッド[MAXN]、N、ヴァル[MAXN]。
22  LLのTOT [MAXN]、DIS [MAXN]、[MAXN] F。
23  LLの合計。
24インラインボイド追加(INT  からINTに、int型のDIS){
 25      [++ NUM] .nxt =先頭から]。
26      [NUM] = .TO に、
27      [NUM] .DISの=のDIS。
28      ヘッド【から】= NUM。
29  }
 30 LL DFS(INT今、int型{FA)を
 31      ため(登録をint ; iは= I =ヘッド[今] {[I] .nxt)
 32          INT =に[I] .TOと、
33          であれば(FAを==ため)続け;
34          LLのRET = (現在の)DFS。
35の          DIS [今] + = DIS + [へ] [I] .DIS * RET。
36の          TOT [今] + = RET。
37      } 
 38      リターン TOTは、[今] TOT [今] + = ヴァル[今]。
39  }
 40  空隙 DP(int型今、INT FA){
 41      (登録をint i =ヘッドは[今];私は私は= {[I] .nxt)
 42          INTを =に[I] .TO。
43          であれば(FAを==する)続けます44         ( - )TOT〔へ] [I] .DIS *(和)+ + - (+ [I] .DIS *)へ] TOT(DIS [に対する] F [今])F = [する] DIS [に];
45          DP(今に)。
46      }
 47  }
 48  、INT (){主
 49      N = (読み取り)
50      のために(登録をint i = 1のval [i]を読み出す=()、和+ = ++ I; iが<= N)のval [I]。
51      のために(登録をint i = 1 ; iがN <; ++ i)が{
 52          INTは X =読み取る()、yは読み取ら=()、Z =を読み取ります()。
53          追加(X、Y、Z)。(Y、X、Z)を追加します。
54     }
 55の      DFS(11 )。
56      F [ 1 ] = DIS [ 1 ]。
57      DP(11 )。
58      LL ANS = 9223372036854775806ll。
59      のために(登録をint i = 1 ; iは= N <; ++ I)ANS = 分(ANS、F [I])。
60      のprintf(" %LLDする\ n " 、ANS)。
61      リターン 0 62 }
ACコード

 

おすすめ

転載: www.cnblogs.com/shl-blog/p/11333167.html