1773:メッセージング

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]。 < INTINT > 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 ; 
}
コードの表示

おすすめ

転載: www.cnblogs.com/betablewaloot/p/12210779.html