hdu4616 Game 【树形dp】

来源:互联网 发布:怎么导入org.apache 编辑:程序博客网 时间:2024/05/17 09:14

题解详见:http://blog.csdn.net/martinue/article/details/51025232
分析透彻。

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<cmath>#include<vector>#include<queue>#include<set>#define ll long longusing namespace std;int getint(){    int i=0,f=1;char c;    for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar());    if(c=='-')f=-1,c=getchar();    for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';    return i*f;}const int N=50005,INF=0x3f3f3f3f;int T,n,C,ans;int val[N],flag[N],dp[N][4][2];int tot,first[N],nxt[N<<1],to[N<<1];void add(int x,int y){    nxt[++tot]=first[x],first[x]=tot,to[tot]=y;}void dfs(int u,int fa){    dp[u][flag[u]][flag[u]]=val[u];    for(int e=first[u];e;e=nxt[e])    {        int v=to[e];        if(v==fa)continue;        dfs(v,u);        for(int i=0;i<=C;i++)            for(int j=0;i+j<=C;j++)            {                if(i+j<=C)ans=max(ans,dp[u][i][1]+dp[v][j][1]);                if(i+j<C) ans=max(ans,dp[u][i][0]+dp[v][j][0]);                if(i!=0)  ans=max(ans,dp[u][i][1]+dp[v][j][0]);                if(j!=0)  ans=max(ans,dp[u][i][0]+dp[v][j][1]);            }        for(int i=0;i<C;i++)        {            dp[u][i+flag[u]][0]=max(dp[u][i+flag[u]][0],dp[v][i][0]+val[u]);            dp[u][i+flag[u]][1]=max(dp[u][i+flag[u]][1],dp[v][i][1]+val[u]);        }        if(!flag[u])dp[u][C][1]=max(dp[u][C][1],dp[v][C][1]+val[u]);    }}int main(){    //freopen("lx.in","r",stdin);    int x,y;    T=getint();    while(T--)    {        memset(dp,-INF,sizeof(dp));        memset(first,0,sizeof(first));        ans=-INF,tot=0;        n=getint(),C=getint();        for(int i=1;i<=n;i++)            val[i]=getint(),flag[i]=getint();        for(int i=1;i<n;i++)        {            x=getint()+1,y=getint()+1;            add(x,y),add(y,x);        }        dfs(1,0);        cout<<ans<<'\n';    }    return 0;}