1773:メッセージング
制限時間:1000msのメモリ制限:262144キロバイト
説明[タイトル]
社会階級Hは、国を守っは、王に加えて、誰もが1を持っており、唯一の直接の優れたが、当然のことながら、王は上司ませんでした。AはBより優れている場合、CにBが高く、次いでA Cが優れています。このような関係はない:AはBの高い、AのBが高くありません。
0は時間の始まりです、あなたはそれが一人に伝えるメッセージを入れた時の1つの単位を使用することですしなければならない、それがニュースに自分自身を広めましょう。いつでもユニット、すべての人がメッセージを受信した、あなたは彼の即時の優れたまたは直接レポートにニュースを伝えることができます。
さて、あなたが知りたいです:
①最終的にどのくらいの時間、H国のすべてを通じてメッセージを広めるためには?
②メッセージを作成するための時間は、最短転送中に何人の選択肢を消費していますか?
[入力]
数に応じてNキングズ数でコンパイル人が1である場合、N、H整数最初の行は、人々の総数を表します。
第二行は、N(N-1コ行)、各ラインの整数、iは優れた即時人々の数を表し、i番目の行番号の整数を行に。
[出力]
出力は、2つの行を合計しました:
最初の行の最後の人がメッセージを受信する最も早い時間を表す整数。
スペースで区切られた番号順に小から大出力に、選択する人の数を示す数の第二の行番号。
[サンプル]入力
4
。1
。1
。1
[]出力例
。4
。1 2 4 3
サンプル2の[Enter]
8
。1
。1
。3
。4
。4
。4
。3
[2]出力サンプル
5
。3. 4. 5. 6. 7
[データサイズと一致]
データ、N≤3000の20%。
データ、N≤20000の50%。
データの100%、N≤200000します。
[説明]
実際には水が問題です。
UのルートがそのサブツリーコストF [U]を送信終了ように、それは容易に決定することができます。
価格はその父とそのトップ・ポイントの後にして決定される方法を考えてみましょう。
変更のルートDPを使用してください。そうG [U]すなわち、uは根ざし父をサブツリーとして除去し、Uの総コストを表します。
fとgのすべての人の息子彼らの並べ替え後には、Gのすべての人の息子を見つけることができます。
各点は計算に非常に良い答え。
コードは以下の通りであります:
#include <ビット/ STDC ++ H> 使用して 名前空間STDを、 CONST INT N = 2E5 + 5 。 int型の F [N]、G [N]、N [N]最後に、サイズ、予め[N]、サブ[N]、ANS [N]、ANS1 = 999999999 、大安[N]、ANS2。 構造体PIGU { int型のDAO、NE。 } [N]。 対 < INT、INT > B [N]。 インラインボイド lingjiebiao(int型のx、int型Y) { [ .dao = ++サイズ] Y。 【サイズ】.NE = 最後[X]。 最後[X] = サイズ。 } インラインボイド DFS1(INT 今は) { ため(INT iが最後[今] =; I;私は= [I] .NE) DFS1([I] .dao)を、 int型 CNT = 0 ; 用(INT ;私は= [今] iが最後= [I] .NE) B [ ++ CNT] = make_pair(F [i]が.dao]、[I] .dao)を、 ソート(B + 1、B + CNT + 1 )。 以下のために(INT iが= 1 ; I <= CNT; iが++ ) F [今] = MAX(F [今]、B [i]は1次回+ CNT-I + 1 )。 } インライン無効 DFS2(INT 今) { int型 CNT = 0 。 以下のために(INT iは最後[今] =; iは、iは= [I] .NE) { Bを[ ++ CNT] = make_pair(F [i]が.dao]、[I] .dao)。 } もし(!今= 1)B [++ CNT = make_pair(G [今] - 1 )。 もし(CNT == 1 &&今== 1)G [今] = 1 。 ソート(B + 1、B + CNT + 1 )。 以下のための(int型 I = 1; iは<= CNT; I ++)ANS [今] MAX(Bは= [i]が1次回+ CNT-I +1、ANS [今]);プレ[ 0 ] =サブ[CNT + 1 ] = - 1 。 以下のために(INT iが= 1 ; iが<= CNT; I ++)[I] = MAX(予備[1-プレ1 ]、B [i]は1次回+ CNT- I)。 用(INT I = CNT; I> = 2 ; i--)サブ[I] = MAX(サブ[I + 1 ]、B [i]は1次回+ CNT-I + 1 )。 用(INT iは= 1 ; I <= CNT; I ++ ) { 場合(!B [i]は.second = - 1 ) G [B [i]は.second] = MAX(予備[I- ])。1 []、サブI + 1 } ため(INT iが最後[今] =; I;私は= [I] .NE)DFS2([I] .dao)を、 } int型のmain() { scanf関数(" %のD "、&N) 以下のために(INT iが= 2、X、; I <= N; I ++ ) { scanf関数(" %のD "、&x)は、 lingjiebiao(X、I)。 } DFS1(1 )。 DFS2(1 )。 以下のために(INT iが= 1 ; I <= N; I ++場合) (ANS1> ANS [i])とANS1 = ANS [i]は、大安は[ANS2 = 1 ] = iが、 他の 場合(ANS1 == ANS [i])と大安[++ ANS2] = iが、 coutの << ANS1 + 1 << " \ n個" ; 以下のために(INT iが= 1 ; I <= ANS2; I ++)COUT <<大安[I] << " " 。 リターン 0 ; }