【dp每一天】HDU

来源:互联网 发布:centos 6.8中文输入法 编辑:程序博客网 时间:2024/05/18 01:36

给自己立个flag吧,每天晚上回来想个dp。

hdu - 1520

题目大意:给你一棵树,树上的父节点和子结点不能同时选,问这棵树可以选的权值最大和。

树形dp,用子节点的值来更新父节点。

有dp[i][0] = sum(max(dp[j][0],dp[j][1])); i->j;

dp[i][1] = sum(dp[j][0]) + d[i]; i->j;

这个因为自己智障还re(!?),忘记清空edgenum这个值了,导致无限加边。晚上脑子也得清醒啊

代码:

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int maxn = 6000+50,inf = 0x3f3f3f3f;int n;int d[maxn];int dp[maxn][2];struct node{    int to,next;    node(){}    node(int a,int b){to = a; next = b;}}edge[maxn<<2];int deg[maxn],h[maxn];int edgenum;void add(int f,int t){    edge[edgenum] = node(t,h[f]);    h[f] = edgenum ++;}void dfs(int u){    int res = 0,res2 = 0;    if(dp[u][0] != -inf) return;    if(h[u] == -1)    {        dp[u][0] = 0;        dp[u][1] = d[u];        return;    }    for(int i = h[u]; ~i ; i = edge[i].next)    {        int v = edge[i].to;        dfs(v);        res += (max(dp[v][1],dp[v][0]));        res2 += dp[v][0];    }    dp[u][0] = res;    dp[u][1] = res2 + d[u];    return;}int main(){    int a,b;    while(~scanf("%d",&n))    {        edgenum = 0;        int flag = 0;        for(int i = 1; i <= n; i++) deg[i] = 0,h[i] = -1,dp[i][0] = dp[i][1] = -inf;        for(int i = 1; i <= n ; i++)            scanf("%d",&d[i]);        while(scanf("%d%d",&a,&b) && a+b)        {            add(b,a);            deg[a] ++;        }        int root = -1;        for(int i = 1; i <= n; i++)            if(deg[i] == 0) {root = i;break;}        dfs(root);        printf("%d\n",max(dp[root][0],dp[root][1]));    }    return 0;}


原创粉丝点击