Description

Alice和Bob有一棵树(无根、无向),在第i个点上有ai个巧克力。首先,两人个选择一个起点(不同的),获得点上的巧克力;接着两人轮流操作(Alice先),操作的定义是:在树上找一个两人都没选过的点并获得点上的巧克力,并且这个点要与自己上一次选的点相邻。当有一人无法操作 时,另一个人可以继续操作,直到不能操作为止。因为Alice和Bob是好朋友,所以他们希望两人得到的巧克力总和尽量大,请输出最大总和。

Solution

我们可以发现,答案一定是由两条不想交的链组成的。
那么问题就是怎么处理,发现打的时候,如果两段链最近的距离只差1的话会很难搞。
我们分类讨论一下:
1、两段链的最高点,互不为祖辈关系,那么这个很好处理,最大值+次大值就好了。
2、当两段链的最高点有一个是另一个的祖先的话,那么我们枚举一个x,那么x的一个节点y中选取y的子树内的最大链,然后x有两种情况,一个是除了y的其他儿子的最大值和次大值组合起来,或者是x向下延伸,然后在向上延伸再从一个z点折下来。
用DP处理一下就可以了。

Code

#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fod(i,a,b) for(i=a;i>=b;i--)
#define rep(i,a) for(i=first[a];i;i=next[i])
using namespace std;
typedef long long ll;
const int maxn=2e5+7;
int i,j,k,l,t,n,m;
int first[maxn*2],last[maxn*2],next[maxn*2],num;
ll a[maxn],f[maxn],g[maxn],b,c,ans;
ll d[maxn],qian[maxn],hou[maxn];
ll qc[maxn],hc[maxn],p[maxn];
ll da1,cda1;
void add(int x,int y){
last[++num]=y,next[num]=first[x],first[x]=num;
}
void dfs(int x,int y){
int i;
ll da=0,cda=0,yi=0,er=0;
rep(i,x){
if(last[i]!=y){
dfs(last[i],x);
g[x]=max(g[x],g[last[i]]);
f[x]=max(f[x],f[last[i]]);
if(da<g[last[i]])cda=da,da=g[last[i]];
else if(g[last[i]]>cda)cda=g[last[i]];
if(yi<f[last[i]])er=yi,yi=f[last[i]];
else if(f[last[i]]>er)er=f[last[i]];
}
}
g[x]+=a[x];
f[x]=max(f[x],a[x]+da+cda);
ans=max(ans,yi+er);
}
void dfs1(int x,int y,ll z){
int i,j;
ll da=0,cda=0;
rep(i,x){
if(last[i]!=y){
if(da<g[last[i]])cda=da,da=g[last[i]];
else if(g[last[i]]>cda)cda=g[last[i]];
}
}
rep(i,x){
if(last[i]!=y){
if(g[last[i]]==da){
if(z<cda)dfs1(last[i],x,cda+a[x]);
else dfs1(last[i],x,z+a[x]);
}
else{
if(z<da)dfs1(last[i],x,da+a[x]);
else dfs1(last[i],x,z+a[x]);
}
}
}
d[0]=0;
rep(i,x)if(last[i]!=y)d[++d[0]]=last[i];
qian[0]=qc[0]=0;
hou[d[0]+1]=hc[d[0]+1]=0;
if(x==4){
ans=ans;
}
fo(i,1,d[0]){
if(g[d[i]]>qian[i-1])qc[i]=qian[i-1],qian[i]=g[d[i]];
else if(g[d[i]]>qc[i-1])qian[i]=qian[i-1],qc[i]=g[d[i]];
else qian[i]=qian[i-1],qc[i]=qc[i-1];
}
fod(i,d[0],1){
if(g[d[i]]>hou[i+1])hc[i]=hou[i+1],hou[i]=g[d[i]];
else if(g[d[i]]>hc[i+1])hou[i]=hou[i+1],hc[i]=g[d[i]];
else hou[i]=hou[i+1],hc[i]=hc[i+1];
}
fo(i,1,d[0]){
da=cda=0;
if(qian[i-1]>da)cda=da,da=qian[i-1];
else if(qian[i-1]>cda)cda=qian[i-1];
if(qc[i-1]>da)cda=da,da=qc[i-1];
else if(qc[i-1]>cda)cda=qc[i-1];
if(hou[i+1]>da)cda=da,da=hou[i+1];
else if(hou[i+1]>cda)cda=hou[i+1];
if(hc[i+1]>da)cda=da,da=hc[i+1];
else if(hc[i+1]>cda)cda=hc[i+1];
ans=max(ans,da+cda+a[x]+f[d[i]]);
ans=max(ans,z+a[x]+da+f[d[i]]);
}
}
int main(){
// freopen("fan.in","r",stdin);
scanf("%d",&n);
fo(i,1,n)scanf("%d",&a[i]);
fo(i,1,n-1){
scanf("%d%d",&k,&l);
add(k,l),add(l,k);
}
dfs(1,0);
dfs1(1,0,0);
printf("%lld\n",ans);
}