hdu4276The Ghost Blows Light 树形dp+分组背包

来源:互联网 发布:淘宝图片侵权处罚 编辑:程序博客网 时间:2024/06/01 21:30
//给一棵树,N个点每个点都有财宝,//要在T时间从点1到点N且能得到的最大权值//一遍dfs记录从1到N的路径所要经过的点x个//然后通过这一条路径将这棵树拆开x个子树//对于这x棵子树dp[i][j]表示以i点为根的子树用时间j//最多能得到多少宝藏//用一个分组背包可以做#include<cstdio>#include<cstring>#include<iostream>#include<vector>using namespace std ;const int maxn = 110 ;int dp[maxn][maxn*5] ;int vis[maxn] ;struct Edge{    int v , w ;    int next ;}edge[maxn<<1] ;int head[maxn] ;int nedge ;int n , T ;int a[maxn] ;void addedge(int u  , int v , int w){    edge[nedge].v = v ;    edge[nedge].w = w ;    edge[nedge].next = head[u] ;    head[u] = nedge++ ;}int dfs(int u , int pre){    if(u == n)    {        vis[n] = 1 ;        return 0 ;    }    for(int i = head[u];i != -1 ; i = edge[i].next)    {        int v = edge[i].v ;        if(v == pre)continue ;        int tmp = dfs(v , u) ;        if(tmp != -1)        {            vis[u] = 1 ;            return tmp+edge[i].w ;        }    }    return -1 ;}void dfss(int u , int pre){    for(int i = head[u];i != -1 ; i = edge[i].next)    {        int v = edge[i].v ;        if(v == pre || vis[v])continue ;        dfss(v , u) ;        for(int j = T;j >= 2*edge[i].w;j--)           for(int k = 0;k <= j-2*edge[i].w;k++)           dp[u][j] = max(dp[u][j] , dp[v][k] + dp[u][j-k-edge[i].w*2]) ;    }    for(int i = 0;i <= T;i++)    dp[u][i] += a[u] ;}int main(){    //freopen("in.txt" , "r" , stdin) ;    while(~scanf("%d%d" , &n , &T))    {        memset(head , -1 , sizeof(head)) ;        memset(vis , 0 , sizeof(vis)) ;        memset(dp , 0 , sizeof(dp)) ;        nedge = 0 ;        for(int i = 1;i < n;i++)        {            int u , v , w ;            scanf("%d%d%d" , &u , &v , &w) ;            addedge(u , v , w) ;            addedge(v , u , w) ;        }        for(int i = 1;i <= n;i++)        scanf("%d" , &a[i]) ;        int tmp = dfs(1 , -1) ;        if(tmp > T)        {            puts("Human beings die in pursuit of wealth, and birds die in pursuit of food!") ;            continue ;        }        int ans = 0 ;        for(int i = 1;i <= n;i++)        if(vis[i])        {            dfss(i , -1) ;            for(int j = T;j >= 0;j--)              for(int k  = 0;k <= j;k++)              dp[0][j] = max(dp[0][j] , dp[i][k] + dp[0][j-k])  ;        }        for(int i = 0;i <= T-tmp;i++)        ans = max(ans , dp[0][i]) ;        cout<<ans<<endl;    }    return 0 ;}

0 0
原创粉丝点击