蔬菜

题目描述

您正站在森林中最显眼的一棵树前,一条叫 Skqliao 的人正在树上打盹,他告诉您这棵树是一棵无根树,在第 i 个点上有 x 颗蔬菜,如果您想要回去的话就需要收集尽量多的蔬菜。当然乐于助人的 Skqliao 也会帮助您。具体来讲,首先你和 Skqliao 各选择一个不同的起点,接着轮流选定一个与自己相邻的且两人都未经过的点并到达该点。当某人无法移动时,另一人可以继续移动,直到两人都无法移动为止。当你或 Skqliao 经过某点时就可以收集该点所有蔬菜,请你制定合理策略 (包括 Skqliao 选择的初始位置和操作方式) 尝试获得最多的蔬菜。

题解

大力分讨,显然拎出来一个点,要么是在这个点的子树内,要么是树外再连进来,各种撞车情况分讨一下即可

代码

#include <bits/stdc++.h>
#define maxn 200005
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
int read(){
    int res,f=1; char c;
    while(!isdigit(c=getchar())) if(c=='-') f=-1; res=(c^48);
    while(isdigit(c=getchar())) res=(res<<3)+(res<<1)+(c^48);
    return res*f;
}
struct EDGE{
    int u,v,nxt;
}e[maxn<<1];
int cnt,head[maxn];
void add(int u,int v){e[++cnt]=(EDGE){u,v,head[u]}; head[u]=cnt;}
int n,w[maxn];
LL ans,dn1[maxn],dnn1[maxn],dn2[maxn],dnn2[maxn],dn3[maxn],s1[maxn],sn1[maxn],s2[maxn],sn2[maxn],up[maxn];
void DFS_1(int u,int far){
    for(int i=head[u];~i;i=e[i].nxt){
        int v=e[i].v; if(v==far) continue;
        DFS_1(v,u);
        if(dn1[v]+w[v]>=dn1[u]){
            dn3[u]=dn2[u];
            dn2[u]=dn1[u]; dnn2[u]=dnn1[u];
            dn1[u]=dn1[v]+w[v]; dnn1[u]=v;
        }
        else if(dn1[v]+w[v]>=dn2[u]){
            dn3[u]=dn2[u];
            dn2[u]=dn1[v]+w[v]; dnn2[u]=v;
        }
        else if(dn1[v]+w[v]>=dn3[u]){
            dn3[u]=dn1[v]+w[v];
        }
        LL tmp=max(s1[v],dn1[v]+dn2[v]+w[v]);
        if(tmp>=s1[u]){
            s2[u]=s1[u]; sn2[u]=sn1[u];
            s1[u]=tmp; sn1[u]=v;
        }
        else if(tmp>=s2[u]){
            s2[u]=tmp; sn2[u]=v;
        }
    }
}
void DFS_2(int u,int far){
    for(int i=head[u];~i;i=e[i].nxt){
        int v=e[i].v; if(v==far) continue;
        up[v]=up[u]+w[u];
        if(dnn1[u]!=v) up[v]=max(up[v],dn1[u]+w[u]);
        else up[v]=max(up[v],dn2[u]+w[u]);
        DFS_2(v,u); 
    }
}
int main(){
    memset(head,-1,sizeof head);
    n=read();
    for(int i=1;i<=n;i++) w[i]=read();
    for(int i=1,u,v;i<n;i++){
        u=read(); v=read();
        add(u,v); add(v,u);
    }
    DFS_1(1,0); DFS_2(1,0);
    for(int i=1;i<=n;i++){
        //cout<<" "<<i<<" "<<dn1[i]<<" "<<dn2[i]<<" "<<dn3[i]<<" "<<s1[i]<<" "<<s2[i]<<" "<<up[i]<<endl;
        ans=max(ans,s1[i]+s2[i]); ans=max(ans,up[i]+dn1[i]+dn2[i]+w[i]);
        if(sn1[i]!=dnn1[i]){
            if(sn1[i]!=dnn2[i]) ans=max(ans,s1[i]+dn1[i]+max(up[i],dn2[i])+w[i]);
            else{
                ans=max(ans,s1[i]+dn1[i]+max(up[i],dn3[i])+w[i]);
                if(sn2[i]!=dnn1[i]) ans=max(ans,s2[i]+dn1[i]+max(up[i],dn2[i])+w[i]);
                else ans=max(ans,s2[i]+dn2[i]+max(up[i],dn3[i])+w[i]);
            }
        }
        else{
            ans=max(ans,s1[i]+dn2[i]+max(up[i],dn3[i])+w[i]);
            if(sn2[i]!=dnn2[i]) ans=max(ans,s2[i]+dn1[i]+max(up[i],dn2[i])+w[i]);
            else ans=max(ans,s2[i]+dn1[i]+max(up[i],dn3[i])+w[i]);
        }
    }
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_32461955/article/details/83548414
今日推荐