hdu 4276 树形dp + 最短路

来源:互联网 发布:电脑流量防火墙软件 编辑:程序博客网 时间:2024/05/08 12:52

n个点各有权值val [ i ], 总时间为T,n-1条双向边,u->v,从u走到v 花费为w, 求在花费不超过T的情况下,能获得的经过的各点权值之和最大。

分析:首先预处理出一条从点1 ~ N的最短路, 那么最优路径的主干一定是经过该最短路的。然后是否走其他的点取决于是否有多出的时间(很显然。)。而且经过最短路之外的点的话,那些点要么不走要么走且只走两次(来回)。

所以先预处理出一条最短路之后,最短路上的点权值改为0,然后用树形dp解决是否要取旁边的点。设dp [ u ][ j ]为走到 u 时花费为 j ,那么

dp[u][j] = max(dp[u][j], dp[v][k] + dp[u][j - weit - k]);
完整代码如下:

#include<stdio.h>#include<string.h>#include<algorithm>#include<iostream>#define N 105using namespace std;int a[N];struct node{    int to, nxt, cost;}edge[N * 3];int head[N];int dp[N][N * 5];int cnt;int n, t;int tt;void init(){    cnt = 0;    memset(head, -1, sizeof(head));}void addedge(int u, int v, int w){    edge[cnt].to = v;    edge[cnt].cost = w;    edge[cnt].nxt = head[u];    head[u] = cnt++;}int dfs1(int u, int pre){    if(u == n)    {        return 1;    }    for( int i = head[u]; ~i; i = edge[i].nxt )    {        int v = edge[i].to;        if(v == pre)            continue;        if(dfs1(v, u))        {            tt += edge[i].cost;            edge[i].cost = 0;            return 1;        }    }    return 0;}void dfs2(int u, int pre){    for(int i = 0; i <= t; i++)        dp[u][i] = a[u];    for( int i = head[u]; ~i; i = edge[i].nxt )    {        int v = edge[i].to;        if(v == pre)            continue;        dfs2(v, u);        int weit = edge[i].cost * 2;        for(int j = t; j >= weit; j--)            for(int k = 0; k <= j - weit; k++)                dp[u][j] = max(dp[u][j], dp[v][k] + dp[u][j - weit - k]);    }}int main(){    while(~scanf("%d%d", &n, &t))    {        init();        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]);        tt = 0;        dfs1(1, -1);        if(tt > t)        {            puts("Human beings die in pursuit of wealth, and birds die in pursuit of food!");            continue;        }        t -= tt;        dfs2(1, -1);        printf("%d\n", dp[1][t]);    }    return 0;}


0 0
原创粉丝点击