忍者の関係も実際には、この質問はツリーです。
B [i]は彼の上司ですが、また彼の親
親ノードは、いくつかの息子を持っていること
親子関係は息子に父親ができ、関係を伝えるためのコマンドであります
あなたがマネージャーを選択するのであれば、彼は木のルートであります
限り、父親忍者のマネージャーとして、我々はメッセンジャーことができるので、
だから、管理者は忍者の範囲を選択することができ、すべての彼の子孫であります
メッセンジャーは、管理者がすることができ、忍者を擁立することはできません
忍者を選ぶときに、あなたが選択したポイントの父親も選択して、この要件はありません。
その後、スタックにすべてのポイント、そしてワットソートの値に応じて再起動さ、マージ
最大値を見つけるために十分なを削除します
// 思考:列挙を送られました。この問題は実際には非常に予約されている、列挙マネージャ、 // しかし、列挙の方法がある の#include <cstdioを> する#include <cstdlib> 書式#include <ベクトル> 書式#include <キュー> 使用して 名前空間STD; int型N-、M、 ロング ロングANS; のconst int型 N = 100003 ; ベクター < INT > ソン[N]; int型B [N]、W [N]、ヴァル[N]; int型FA [Nを]; int型の検索(INT X){ 戻り FA [X] == 0 X :? FA [X] = 検索(FA [X]);} int型(マージINT A、INT B)// 这里是W的堆最大 { 場合(A == B)を返します。 もし(W [A] <= W [B])戻り FA [A] = ; B、息子[B] .push_back(A)、Bを 他を 返す FA [B] = 、息子[A] .push_back(B)。 } int型デル(INT X) { キュー < INT > S。 INT SIZ = 息子[X] .size()。 以下のために(int型 i = 0 ; iはSIZ <; iは++ ) { int型、T =息子の[X] [i]は、 FA [T] = 0 ; s.push(T)。 } 一方((SIZ - )> 1 ) { int型 A = s.front(); s.pop()。 INT B = s.front(); s.pop()。 s.push(B)、(マージ)。 } もし FA [X] =(s.empty()!)s.front(); 息子[X] .clear(); 戻り[X、W。 } INT SZ [N]。 長い 長い和[N]。 INT メイン() { scanf関数(" %d個の%のD "、&N、&M)。 にとって(のInt I = 1。 ; I <= N; I ++は) { scanfの(" %D%D%D "、&B [I]、&W [I]、&ヴァル[I]); ANS = MAX((ロング ロング)ヴァル[I]、ANS); // 1 SZ [I] = 1。、[I] = SUM W [I]; } ため(INT I = N-; I; i--)// ボス各ニンジャその数は、<Iバイの数よりも小さくなければならない // 上がる、(すなわち、底部である)、このさえオイラー配列をNから横断、保存されている { INT F = Bを[I]; // これは、ルートである SZ [F ] = SZ + [I]、SUM [F] + = SUM [I]、 マージ((F)検索、(I)の検索);// !!!!!!!直接、ここでF書かないで // つ以上の息子があり、F、マージオーバーの前に引き出されているため、(f)はFとは必ずしも同じではありません見つける しばらく(SUM [F]> M) { SUM [F] - = デル(検索(F)); SZ [F] - ; } ANS = MAX(ANS、SZ [F] * 1LL ヴァル[F]); } のprintf(" %のLLD " 、ANS); 戻り 0 ; }