codeforces743D 【DFS】

题意:
给你一棵以1为root的根,然后让你求两棵不相交子树的最大和;
思路:
DFS,主要就是你一定得使两棵子树不相交;
对于一个顶点u,维护以u为根的最大子树和。
①:包含u,即所有的结点和。
②:不包含,在子树内找一个最大子树。
每次对于一个根搞搞就好了,维护一下答案;
这个DFS真的赞。。一开始wa4还是那个没有保证子树不相交,后来RE5 and WA5 DFS的函数int应该写LL...(菜啊!
大家都说是树型DP...在弱弱眼里就是个DFS啊ヽ(*。>Д<)o゜......

//赛后qqq神的一句话总结得真好:子树 sum 和 子树内的子树最大 sum

#include<bits/stdc++.h>
using namespace std;
typedef __int64 LL;
const LL INF=-1e18;
const int N=2e5+10;
int n;
LL val[N];

struct asd
{
    int to;
    int next;
};

asd q[2*N];
int head[2*N],tol;

void add(int u,int v)
{
    q[tol].to=v;
    q[tol].next=head[u];
    head[u]=tol++;
}

LL ans;
bool vis[N];
int DFS(int u,LL &W)
{
    vis[u]=1;
    LL sum=val[u];
    LL ans1,ans2;
    ans1=ans2=INF;
    for(int i=head[u];i!=-1;i=q[i].next)
    {
        if(vis[q[i].to])
            continue;
        LL tmp;
        sum+=DFS(q[i].to,tmp);
        if(tmp>ans1)
        {
            ans2=ans1;
            ans1=tmp;
        }
        else if(tmp>ans2)
            ans2=tmp;
    }
    if(ans2!=INF)
        ans=max(ans,ans1+ans2);
    W=max(sum,ans1);
    return sum;
}

int main()
{
    scanf("%d",&n);
    for(int i=1; i<=n; i++)
        scanf("%I64d",&val[i]);
    int u,v;
    tol=0;
    memset(head,-1,sizeof(head));
    for(int i=1; i<n; i++)
    {
        scanf("%d%d",&u,&v);
        add(u,v);
        add(v,u);
    }

    ans=INF;
    memset(vis,0,sizeof(vis));
    LL tmp;
    DFS(1,tmp);
    if(ans!=INF)
        printf("%I64d\n",ans);
    else
        puts("Impossible");
    return 0;
}


posted @ 2016-12-15 17:52  see_you_later  阅读(192)  评论(0编辑  收藏  举报