HDU 5834 Magic boy Bi Luo with his excited tree

树形dp。

先dfs一次处理子树上的最优解,记录一下回到这个点和不回到这个点的最优解。

然后从上到下可以推出所有答案。细节较多,很容易写错。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<iostream>
#include<ctime>
using namespace std;
typedef long long LL;
const double pi=acos(-1.0);
void File()
{
    freopen("D:\\in.txt","r",stdin);
    freopen("D:\\out.txt","w",stdout);
}

const int maxn=100010;
vector<int>G[maxn],t[2][maxn][2];
int T,n,v[maxn],dp[maxn][2],ans[maxn],sz;
struct Edge{int u,v,w;}e[2*maxn];
bool flag[maxn];

void add(int a,int b,int c)
{
    e[sz].u=a; e[sz].v=b; e[sz].w=c;
    G[a].push_back(sz++);
}

void dfs(int x,int f)
{
    flag[x]=1; dp[x][0]=dp[x][1]=v[x];

    int i; if(f==0) i=0; else i=G[x].size()-1;
    while(1)
    {
        if(f==0&&i==G[x].size()) break; if(f==1&&i==-1) break;

        int id=G[x][i],to=e[id].v;
        if(flag[to])
        {
            t[f][x][0].push_back(dp[x][0]); t[f][x][1].push_back(dp[x][1]);
            if(f==0) i++; else i--; continue;
        }

        dfs(to,f);

        int t1=dp[x][1], t2=dp[x][0]+dp[to][1]-e[id].w, t3=dp[x][1]+dp[to][0]-2*e[id].w;
        dp[x][1]=max(t1,max(t2,t3));
        dp[x][0]=dp[x][0]+max(dp[to][0]-2*e[id].w,0);

        t[f][x][0].push_back(dp[x][0]); t[f][x][1].push_back(dp[x][1]);
        if(f==0) i++; else i--;
    }

}

void get(int x,int a,int b,int c)
{
    flag[x]=1;

    int t1=dp[x][1];
    int t2=dp[x][0]+b-c;
    int t3=a+dp[x][1]-2*c;

    ans[x]=max(t1,max(t2,t3));

    int SZ=G[x].size();

    for(int i=0;i<SZ;i++)
    {
        int id=G[x][i],to=e[id].v;
        if(flag[to]) continue;
        int na=0,nb=0,dp0=0,dp1=0, x1=0,x2=0,y1=0,y2=0;
        if(i-1>=0) x1=t[0][x][0][i-1];
        if(SZ-1-(i+1)>=0) x2=t[1][x][0][SZ-1-(i+1)];
        if(i-1>=0) y1=t[0][x][1][i-1];
        if(SZ-1-(i+1)>=0) y2=t[1][x][1][SZ-1-(i+1)];
        dp0=x1+x2; if(x1!=0&&x2!=0) dp0=dp0-v[x];
        int k1,k2;
        k1=x1+y2;  if(x1!=0&&y2!=0) k1=k1-v[x];
        k2=x2+y1;  if(x2!=0&&y1!=0) k2=k2-v[x];
        dp1=max(k1,k2);
        dp0=max(dp0,v[x]); dp1=max(dp1,v[x]);
        na=max(dp0,dp0-2*c+a); nb=max(dp1,max(dp0+b-c,a+dp1-2*c));
        get(to,na,nb,e[id].w);

    }

}

int main()
{
    scanf("%d",&T); int cas=1;
    while(T--)
    {
        scanf("%d",&n); sz=0;

        memset(dp,0,sizeof dp);
        for(int i=0;i<=n;i++)
        {
            G[i].clear();
            t[0][i][0].clear(); t[0][i][1].clear();
            t[1][i][0].clear(); t[1][i][1].clear();
        }

        for(int i=1;i<=n;i++) scanf("%d",&v[i]);
        for(int i=1;i<=n-1;i++)
        {
            int u,v,w; scanf("%d%d%d",&u,&v,&w);
            add(u,v,w); add(v,u,w);
        }

        memset(flag,0,sizeof flag); dfs(1,0);
        memset(flag,0,sizeof flag); dfs(1,1);

        memset(flag,0,sizeof flag); get(1,0,0,0);

        printf("Case #%d:\n",cas++);
        for(int i=1;i<=n;i++) printf("%d\n",ans[i]);
    }
    return 0;
}

 

posted @ 2016-08-19 07:10  Fighting_Heart  阅读(285)  评论(0编辑  收藏  举报