Acesrcと旅行

 Acesrcと旅行

制限時間:1秒   メモリ制限:128メガバイト

タイトル説明

Acesrcは誰にも負けない南京大学の有名な観光です。この夏休みの間に、彼、張と劉と一緒に、香港に旅行する予定です。これらのスポットを結ぶn-1の双方向観光バス路線があり、香港におけるNスポットがある、と。彼らはバスでいくつかのスポットを訪問することにしました。

しかし、張と劉は、これらのスポットのために異なる嗜好を持っています。彼らは、それぞれ各スポットについて良好な値を設定します。彼らはi番目のスポットを訪問した場合、張は良好な値AIを取得する、と劉は双方向取得します。張以降では、彼らが交互に公正のために訪問する次のスポットを決めます。現在のスポットと訪問する次のスポット間のバス路線が存在する必要があります。また、彼らは二回スポットを訪問したいことはありません。誰が訪問するように次のスポットを見つけることができない場合、彼らはこの旅を終わらざるを得ません。

張と劉さんは、両方のスーパースマート競争力のプログラマです。どちらかが彼の合計良好な値と他の間の差を最大化します。彼らは両方の張と劉の総満足値の差は何ですか、最適に選択した場合、今Acesrcは、不思議?

エントリー

入力の最初の行は、テストケースの数を示す、単一の整数T(1≤T≤30)から成ります。

各テストケースのために、最初の行にはスポットの数を示す、単一の整数n(1≤n≤105)を含みます。次の2行の各々は、N個の整数を、含まA1、A2、⋯、表すとB1、B2、⋯、BN(0≤ai、bi≤109)、 
それぞれ、すべてのスポットについて張と劉の良好な値を。最後のn-1ラインのそれぞれは、yはx番目のスポットとYTHスポット間のバス路線を示す、(1≤x、y≤n、≠yはx)を、二つの整数xを含んでいます。これは、これらのバス路線を通じて、他の場所に任意の地点から到達可能です。

nの合計は5.01×105を超えていないことが保証されています。

輸出

両者が最適に選択した場合、各テストケースのために、1つのライン中の全良好な値の差分を単一の整数を印刷します。

サンプル入力

1 
3 
1 1 1 
0 2 3 
1 2 
1 3

サンプル出力

-1

質問の意味:二人は木を選択するターンを取ると、各点が重みを持って、最大の重みと望んでいた、Bは重みと最小値を望んでいる、次の点を選択するとの選択がありますエッジ点は直接に接続され、選択ポイントを繰り返すことができない、初期点として任意の一点を選択してもよく、そしてQは、最終的な重みの数です。
思考:AまたはBは、特定の点を選択し、ステップは:DPが考えられるが、これは、非ルート付きツリーであり、最初ルート付きツリーDP、すなわち、ルートノードである第1の点1に変換し、その後、DPが算出されますこれは、最適な重みのポイントを変更するために彼の父から来たと。次いで父親DPの裏面を考慮する、すなわち計算:AまたはBは、特定の点を選択し、次のステップは、最適重み点と父を変更することです。答えは最大を維持するために、まったく点Bを選択することです。
概要:ルートレスツリーは、ツリーDP DPプラス父はDPの側を逆に根ざしています。

#pragma GCCの最適化(3、 "Ofast"、 "インライン")
の#include <ビット/ STDC ++ H>
 使用して 名前空間STD。
 
CONSTの INT N = 6E5 + 50 構造体SS 
{ 
    int型、U、V、次; 
}。
SS EDG [N * 2 ]。
int型のヘッド[N]、sum_edge = 0 
 
ボイド addedge(INT U、INT V)
{ 
    EDG [sum_edge] = (SS){U、V、ヘッド[U]}。
    ヘッド[U] = sum_edge ++ 
} 
 
長い 長い値[N]。
長いです 長い ANS = 0 ;
長い 長い DP [N] [ 2 ]。
 
 
無効のinit(int型n)を
{ 
    ためint型 i = 0 ; iが<= N; iは++ 
    { 
        ヘッド[I] = - 1 
        DP [I] [ 0 ] = DP [I] [ 1 ] = 0 
    } 
    sum_edge = 0 
    ANS = LLONG_MIN。
} 
 
長い 長い DFS1(int型のx、int型 FA、INTタイプ)
{ 
    場合(DP [X] [タイプ])戻りDP [X] [タイプ]。
    長い 長い今=(タイプ== 0LLONG_MIN:LLONG_MAX)。
 
    以下のためにint型 - ;!I = [X] i =ヘッド1 ; I = EDG [I] .next)
    { 
        int型 V = EDG [I] .V。
        もし(== FA V)続けます
 
        もし(タイプ== 0)今= MAX(今、DFS1(V、X、1)+ 値[X])。
         =分(今、DFS1(V、X、0)+ 値[X])。
    } 
    リターンDP [X] [タイプ] =((現在== LLONG_MAX ||今== LLONG_MIN)?値[X]:今)。
} 
 
長い 長い DFS(int型のx、int型 FA、INTのタイプ、長い 長いlast_ans)
{ 
   // のprintf( "%D%D%D%LLD \ n"、X、FA、タイプ、last_ans)。
    // のprintf( "X =%dの、FA =%D:%LLD%LLD値[%のD] =%のLLDを\ n"、X、FA、DFS1(X、FA、0)、DFS1(X、FA、 1)中、X、値[X])。
    PRIORITY_QUEUE <ペア< 長い 長いint型 >> Q;
    以下のためにint型 I =ヘッド[X];!I = - 1 ; iは= EDG [I] .next)
    { 
        int型 V =EDG [i]は.V。
        もし(== FA V)続けます
 
        もし(タイプ== 0)q.push(make_pair(-dfs1(V、X、1 )、V))。
        
            q.push(make_pair(DFS1(V、X、0 )、v)で)。
 
        もし(q.size()> 2 )q.pop(); 
    } 
 
    ペア < 長い 長いINT > まず、
    ペア < 長い 長いint型 > 二; 
 
    もし(q.size())
    { 
       最初 = q.top()。
       q.pop(); 
      //printf( "%LLDする\ n"、first.first)。
 
        もし(q.size())
        { 
            第二 = q.top()。
          //   printfの( "%LLDの\ nを"、second.first)。
            q.pop(); 
        } 
        
        {  = 最初; 
 
            もし(!X = 1)第一= make_pair(LLONG_MAX / 2、 - 1 )。
            他の
                第一 = make_pair(0、 - 1 )。
        } 
    } 
    
    { 
        場合(X!= 1)第二= make_pair(LLONG_MAX /2、 - 1 )。
        他の
            第二 = make_pair(0、 - 1 )。
    } 
 
    場合(タイプ== 0 
    { 
        ためint型 I =ヘッド[X]; I =! - 1 ; I = EDG [I] .next)
        { 
            int型 V = EDG [I] .V。
            もし(== FA V)続けます
 
            もし(V == second.second)DFS(V、X、1、MAX(last_ans、-first.first)+ 値[X])。
            他の
                DFS(V、X、1、MAX(last_ans、-second.first)+値[X])。
        } 
    } 
    
    { 
        ANS = MAX(ANS、分(last_ans、second.first)+ 値[X])。
        以下のためにint型 - ;!I = [X] i =ヘッド1 ; I = EDG [I] .next)
        { 
            int型 V = EDG [I] .V。
            もし(== FA V)続けます
 
            もし(V == second.second)DFS(V、X、0、分(last_ans、first.first)+ 値[X])。
            他の
                DFS(V、X、0、分(last_ans、second.first)+ 値[X])。
        } 
    } 
} 
 
int型メイン()
{ 
    int型のT。
    scanf関数(" %のD "、&T)。
    一方、(t-- 
    { 
        int型N。
        scanf関数(" %のD "、&N)
        INIT(N)
 
        以下のためにint型 i = 1 ; iが<= N; iは++ 
        scanf関数を(" %のLLD "、&値[I])。
 
        以下のためにint型 i = 1 ; iが++; iが<= N 
        { 
            長い 長いです
            scanf関数("%のLLD "&A ); 
            値は[i]は - = ; 
        } 
 
        ためint型 i = 1 ; iがn <; iは++ 
        { 
            int型、U、V; 
            scanf関数(" %d個の%のD "、&​​U、&がV)。
            addedge(U、V); 
            addedge(V、U)を; 
        } 
 
     / *    (N <= 2)であれば
        { 
            長い長い和= 0; 
            (; iが<= N; I = 1をint型私は++)用の和+ =値[I ]; 
            のprintf( "%LLDする\ n"、和); 
            続ける; 
        } * / 
 
        DFS(1、 - 10、LLONG_MIN / 2 )。
        DFS(1、 - 11、LLONG_MAX / 2 )。
 
        printf(" %LLDする\ n " 、ANS)。
    } 
    戻り 0 
}
コードの表示

おすすめ

転載: www.cnblogs.com/tian-luo/p/11371555.html