poj1155 TELE 【树形dp】

来源:互联网 发布:世界地图gis数据 编辑:程序博客网 时间:2024/06/06 07:17

链接:http://poj.org/problem?id=1155

题意:以1为根的树,叶子节点上有权值,从1出发到叶子节点会得到叶子的权值,但是要减去路径上的权值,问你最多到达多少叶子使得最后的值大于等于0.

分析:i点为根时用到的叶子节点j的价值用dp[i][j]表示,向上更新的时候就相当于将子树合并。

dp[u][j+k]=max(dp[u][j]+dp[v][k]-w).

代码:

#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<string>#include<vector>#include<queue>#include<cmath>#include<stack>#include<set>#include<map>#define INF 0x3f3f3f3f#define Mn 3010#define Mm 2000005#define mod 1000000007#define CLR(a,b) memset((a),(b),sizeof((a)))#define CLRS(a,b,Size) memset((a),(b),sizeof((a[0]))*(Size+1))#define CPY(a,b) memcpy ((a), (b), sizeof((a)))#pragma comment(linker, "/STACK:102400000,102400000")#define ul u<<1#define ur (u<<1)|1using namespace std;typedef long long ll;struct edge {    int v,w,next;}e[Mm];int tot,head[Mn];void addedge(int u,int v,int w) {    e[tot].v=v;    e[tot].w=w;    e[tot].next=head[u];    head[u]=tot++;}int dp[Mn][Mn];int tmp[Mn],num[Mn];void dfs(int u) {    for(int i=head[u];~i;i=e[i].next) {        int v=e[i].v;        int w=e[i].w;        dfs(v);        for(int j=0;j<=num[u];j++) tmp[j]=dp[u][j];        for(int j=0;j<=num[u];j++) {            for(int k=1;k<=num[v];k++) {                dp[u][j+k]=max(dp[u][j+k],tmp[j]+dp[v][k]-w);            }        }        num[u]+=num[v];    }}int n,m;void init() {    CLR(head,-1);    tot=0;    CLR(num,0);    for(int i=1;i<=n;i++)        for(int j=1;j<=m;j++)            dp[i][j]=-INF;}int main() {    while(~scanf("%d%d",&n,&m)) {        init();        for(int i=1;i<=n-m;i++) {            int k;            scanf("%d",&k);            while(k--) {                int v,w;                scanf("%d%d",&v,&w);                addedge(i,v,w);            }        }        for(int i=n-m+1;i<=n;i++) {            num[i]=1;            scanf("%d",&dp[i][1]);        }        dfs(1);        for(int i=m;i>=0;i--) {            if(dp[1][i]>=0) {                printf("%d\n",i);                break;            }        }    }    return 0;}


0 0