hdu4616(树形dp)

来源:互联网 发布:淘宝会员等级会降低吗 编辑:程序博客网 时间:2024/05/21 10:37

链接:点击打开链接

题意:给出一个树上每个节点的权值和是否有陷阱,最多能遇到m个陷阱,当遇到第m个陷阱时必须停下来,求获得的最大权值使多少

代码:

#include <vector>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <iostream>#include <algorithm>using namespace std;vector<int> G[50005];int n,m,ans;int dp[50005][5][2];int val[50005],vis[50005],sign[50005];void dfs(int s){    int i,j,k,tmp;    vis[s]=1;    dp[s][sign[s]][0]=dp[s][sign[s]][1]=val[s];    for(i=0;i<G[s].size();i++){        tmp=G[s][i];        if(vis[tmp])        continue;        dfs(tmp);        for(j=0;j<=m;j++){                      //相当于在这个节点之前的链和这个节点结合            for(k=0;k+j<=m;k++){                if(j!=m)                ans=max(ans,dp[s][j][0]+dp[tmp][k][1]);                if(k!=m)                ans=max(ans,dp[s][j][1]+dp[tmp][k][0]);                if(j+k<m)                       //全用向上走的话可能走的陷阱数已经到m了却依然再走                ans=max(ans,dp[s][j][0]+dp[tmp][k][0]);                if(j+k<=m)                ans=max(ans,dp[s][j][1]+dp[tmp][k][1]);            }        }        for(j=0;j+sign[s]<=m;j++)               //在用这个节点更新,避免了父节点向下和子节点向上是一条链        dp[s][j+sign[s]][0]=max(dp[s][j+sign[s]][0],dp[tmp][j][0]+val[s]);        for(j=1;j+sign[s]<=m;j++)        dp[s][j+sign[s]][1]=max(dp[s][j+sign[s]][1],dp[tmp][j][1]+val[s]);    }}int main(){    int i,t,u,v;    scanf("%d",&t);    while(t--){        scanf("%d%d",&n,&m);        memset(dp,0,sizeof(dp));        memset(vis,0,sizeof(vis));        for(i=1;i<=n;i++)        G[i].clear();        for(i=1;i<=n;i++)        scanf("%d%d",&val[i],&sign[i]);        for(i=1;i<n;i++){            scanf("%d%d",&u,&v);            u++,v++;            G[u].push_back(v);            G[v].push_back(u);        }        ans=0;        dfs(1);        printf("%d\n",ans);    }    return 0;}

0 0
原创粉丝点击