[HDU6662] Acesrcと旅行(木DP)

トピックリンク

不注意な

ツリーは、各点の重み値が与えられる(A [I] \)\、2つの非常にスマートな人のAとBがあります
AとBのテイクターンの両方がポイントの前に通過しないように、木で一緒に歩きます。(AB時間一緒に)
優勢、及び、開始点を決定することができます。Aは、Bは、重みと最小値と最大点の右側を望んで、走行所望します。
最終重量と求めます。

思考

まず、木のDP非常に明確なアイデアがあります:
セット\(F0 [U] \)で表さ\(U \)サブツリーのルートの中、鎧はちょうどに行く\(U \)の開始点としての重みと。
セット\(F1 [U] \)で表される(U \)\へルートとするサブツリー内で、B上ハンド\(U \)の出発点と重みとして。
その後に式を転送することである:
\(F0 [U] =最小(FL [V])+ A [U] \)
\(FL [U] = MAX(F0 [V])+ A [U] \)
ここで\ (V \)\(U \)の息子。
私たちは、各点の答えに対処できるように、ちょうどそのサブツリーの範囲内で行きます。


配慮のある時点からは、回答フォームを歩きます。

私たちは、セット\(TP [V] \)彼らは行かなかったと述べた\(V \)サブツリーを、鎧だけを取得(V \)\開始点と重みとして。
だから、\(TP [V] \)のアップデートは2例があるでしょう、人は行くことです\(Uを\) その後、行く\(U \)息子の。

この場合には、間違いなく選択A \(U \)の息子(F0 \)\最大値、その\(F1 [U] \)
しかしによる\(V \)が記録されなければならないので、最大であり、それ自体で、可能な場合、(F1 \)を\最大値と二番目に大きい値が転送されます。

別の場合、つまり、行く\(U \) 歩行\(FA \)の状況を。

この場合には、にアクセスしてください(FA \)\際、\(B \)歩行しながら、小さなにそれを選択します。
だから(FA \)\すべての人の息子最小\(F1 \) つまり\(F0 [Faを] \)\(FA \)例が上がる(\ TP [Faを])\少ないライン上の方は、 A。
しかし同様に、\(U- \)は、次のレコードに、可能な限り最小である\(F0 \)の最小値と二番目に小さい値が転送されます。

両方のための\(TP \)がある場合であるため、選択された(A \)は\方が大きくなるように、選択されます。
注:転送\(TP \) 鎖の場合に注意を払うまでの時間。

最後に、出発点として列挙し、その時点で、取る\(F0 [U] [0 ] \) と\(TP [U] \)ライン上の小さい方の値の。

ルート値にそのリーフノードに注意してください。

コード

より多くのエラーが発生しやすい箇所以上の詳細は、初期割り当てと根に焦点を当てました。

#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int MAXN=600005;
const long long INF=1e17;
int K,N,A[MAXN];
int son0[MAXN],son1[MAXN];
long long Ans;
long long F0[MAXN][2],F1[MAXN][2];//0:A|||||||1:B
long long TP[MAXN];
vector<int>P[MAXN];
void DFS(int u,int fa){
    int Ok=0;
    int size=P[u].size();
    for(int i=0;i<size;i++){
        int v=P[u][i];
        if(v==fa)continue;
        DFS(v,u);Ok=1;
        if(F1[v][0]+A[u]<F0[u][0])F0[u][1]=F0[u][0],F0[u][0]=min(F0[u][0],F1[v][0]+A[u]),son0[u]=v;
        else F0[u][1]=min(F0[u][1],F1[v][0]+A[u]);
        if(F0[v][0]+A[u]>F1[u][0])F1[u][1]=F1[u][0],F1[u][0]=max(F1[u][0],F0[v][0]+A[u]),son1[u]=v;
        else F1[u][1]=max(F1[u][1],F0[v][0]+A[u]);
    }
    if(!Ok)F0[u][0]=F0[u][1]=F1[u][0]=F1[u][1]=A[u];
}
void DFS2(int u,int fa){
    int size=P[u].size();
    for(int i=0;i<size;i++){
        int v=P[u][i];
        if(v==fa)continue;
        long long val1=INF,val2=INF;
        if(P[u].size()!=2){
            if(son1[u]==v)val1=F1[u][1];
            else val1=F1[u][0];
        }else val1=u==1?A[u]:-INF;
        if(P[fa].size()!=2){
            if(son0[fa]==u)val2=F0[fa][1];
            else val2=F0[fa][0];
        }val2=min(val2,TP[fa]);
        TP[v]=A[v]+max(val1,val2+A[u]);
        DFS2(v,u);
    }
}
int main(){
    //freopen("data.txt","r",stdin);
    //freopen("mine.txt","w",stdout);
    scanf("%d",&K);
    while(K--){
        scanf("%d",&N);
        for(int i=0;i<=N;i++){
            F0[i][0]=F0[i][1]=INF;
            F1[i][0]=F1[i][1]=-INF;
            son0[i]=son1[i]=0;TP[i]=-INF;
            P[i].clear();
        }
        for(int i=1;i<=N;i++)scanf("%d",&A[i]);
        for(int i=1,x;i<=N;i++)scanf("%d",&x),A[i]-=x;
        if(N==1){
            printf("%d\n",A[1]);
            continue;
        }
        for(int i=1,x,y;i<N;i++){
            scanf("%d%d",&x,&y);
            P[x].push_back(y);
            P[y].push_back(x);
        }Ans=-INF;P[1].push_back(0);
        DFS(1,0);
        if(P[1].size()!=2)TP[1]=INF;
        else TP[1]=A[1];
        DFS2(1,0);
        Ans=F0[1][0];
        for(int i=2;i<=N;i++){
            if(P[i].size()==1)Ans=max(Ans,TP[i]);
            else Ans=max(Ans,min(F0[i][0],TP[i]));
        }
        printf("%lld\n",Ans);
    }
}

おすすめ

転載: www.cnblogs.com/ftotl/p/11809273.html