不注意な
ツリーは、各点の重み値が与えられる(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);
}
}