zoukankan      html  css  js  c++  java
  • HDOJ树形DP专题之Tree of Tree

    题目链接

    题目大意:给定一棵树,每个结点有一个值,求一棵含k个结点的子树,使子树的值最大。(树的值为所含结点的值的和)

    分析:n最大为100,定义状态dp[u][k]为以结点u为根结点且含k个结点的子树的最大值。用左二子右兄弟来存树,不难写出状态转移方程。

    纠结之处在于使用memset(dp,-1,sizeof(dp))就WA,改成memset(dp,0xff,sizeof(dp))就AC了。其中还有好几次CE莫名其妙,提示信息为"Getting complication error information failed!"

    AC的代码
     1 #include <stdio.h>
     2 #include <memory.h>
     3 #define MAX(a,b) ((a)>(b)?(a):(b))
     4 #define N 101
     5 int son[N],bro[N],n,k;
     6 int u[2*N],v[2*N],next[2*N],first[N];
     7 long long dp[N][N],w[N],ans;
     8 void addEdge(int a,int b,int e)
     9 {
    10   u[e]=a,v[e]=b;
    11   next[e]=first[a];
    12   first[a]=e;
    13 }
    14 void dfs(int a,int fa)
    15 {
    16   int e,b;
    17   for(e=first[a];e>=0;e=next[e])
    18   {
    19     b=v[e];
    20     if(b==fa) continue;
    21     if(son[a]==-1)  son[a]=b;
    22     else  bro[b]=bro[son[a]],bro[son[a]]=b;
    23     dfs(b,a);
    24   }
    25 }
    26 long long dptree(int a,int k)
    27 {
    28   int i,ret;
    29   if(a<0) return 0;
    30   if(dp[a][k]!=-1)  return dp[a][k];
    31   if(k==0)  return dp[a][k]=0;
    32   if(k==1)  return dp[a][k]=w[a];
    33   ret=w[a];
    34   if(son[a]==-1)  return dp[a][k]=ret;
    35   for(i=0;i<k;i++)  ret=MAX(ret,w[a]+dptree(son[a],i)+dptree(bro[son[a]],k-1-i));
    36   return dp[a][k]=ret;
    37 }
    38 int main()
    39 {
    40   int i,j,a,b;
    41   while(~scanf("%d%d",&n,&k))
    42   {
    43     for(i=0;i<n;i++)  scanf("%lld",&w[i]);
    44     memset(next,0xff,sizeof(next));
    45     memset(first,0xff,sizeof(first));
    46     for(i=0;i<n-1;i++)
    47     {
    48       scanf("%d%d",&a,&b);
    49       addEdge(a,b,2*i);
    50       addEdge(b,a,2*i+1);
    51     }
    52     memset(son,0xff,sizeof(son));
    53     memset(bro,0xff,sizeof(bro));
    54     memset(dp,0xff,sizeof(dp));
    55     dfs(0,-1);
    56     ans=0;
    57     for(i=0;i<n;i++)  ans=MAX(ans,dptree(i,k));
    58     printf("%lld\n",ans);
    59   }
    60   return 0;
    61 }
    奇怪的CE
     1 #include <stdio.h>
     2 #include <string.h>
     3 #define MAX(a,b) ((a)>(b)?(a):(b))
     4 #define N 101
     5 int son[N],bro[N],n,k;
     6 int u[2*N],v[2*N],next[2*N],first[N];
     7 long long dp[N][N],w[N],ans;
     8 void addEdge(int a,int b,int e)
     9 {
    10   u[e]=a,v[e]=b;
    11   next[e]=first[a];
    12   first[a]=e;
    13 }
    14 void dfs(int a,int fa)
    15 {
    16   int e,b;
    17   for(e=first[a];e>=0;e=next[e])
    18   {
    19     b=v[e];
    20     if(b==fa) continue;
    21     if(son[a]==-1)  son[a]=b;
    22     else  bro[b]=bro[son[a]],bro[son[a]]=b;
    23     dfs(b,a);
    24   }
    25 }
    26 long long dptree(int a,int k)
    27 {
    28   int i,ret;
    29   if(a<0) return 0;
    30   if(dp[a][k]!=-1)  return dp[a][k];
    31   if(k==0)  return dp[a][k]=0;
    32   if(k==1)  return dp[a][k]=w[a];
    33   ret=w[a];
    34   if(son[a]==-1)  return dp[a][k]=ret;
    35   for(i=0;i<k;i++)  ret=MAX(ret,w[a]+dptree(son[a],i)+dptree(bro[son[a]],k-1-i));
    36   return dp[a][k]=ret;
    37 }
    38 int main()
    39 {
    40   int i,j,a,b;
    41   while(~scanf("%d%d",&n,&k))
    42   {
    43     for(i=0;i<n;i++)  scanf("%lld",&w[i]);
    44     memset(next,-1,sizeof(next));
    45     memset(first,-1,sizeof(first));
    46     for(i=0;i<n-1;i++)
    47     {
    48       scanf("%d%d",&a,&b);
    49       addEdge(a,b,2*i);
    50       addEdge(b,a,2*i+1);
    51     }
    52     memset(son,-1,sizeof(son));
    53     memset(bro,-1,sizeof(bro));
    54     memset(dp,-1,sizeof(dp));
    55     dfs(0,-1);
    56     ans=0;
    57     for(i=0;i<n;i++)  ans=MAX(ans,dptree(i,k));
    58     printf("%lld\n",ans);
    59   }
    60   return 0;
    61 }
    WA的代码
     1 #include <stdio.h>
     2 #include <memory.h>
     3 #define MAX(a,b) ((a)>(b)?(a):(b))
     4 #define N 101
     5 int son[N],bro[N],n,k;
     6 int u[2*N],v[2*N],next[2*N],first[N];
     7 long long dp[N][N],w[N],ans;
     8 void addEdge(int a,int b,int e)
     9 {
    10   u[e]=a,v[e]=b;
    11   next[e]=first[a];
    12   first[a]=e;
    13 }
    14 void dfs(int a,int fa)
    15 {
    16   int e,b;
    17   for(e=first[a];e>=0;e=next[e])
    18   {
    19     b=v[e];
    20     if(b==fa) continue;
    21     if(son[a]==-1)  son[a]=b;
    22     else  bro[b]=bro[son[a]],bro[son[a]]=b;
    23     dfs(b,a);
    24   }
    25 }
    26 long long dptree(int a,int k)
    27 {
    28   int i,ret;
    29   if(a<0) return 0;
    30   if(dp[a][k]!=-1)  return dp[a][k];
    31   if(k==0)  return dp[a][k]=0;
    32   if(k==1)  return dp[a][k]=w[a];
    33   ret=w[a];
    34   if(son[a]==-1)  return dp[a][k]=ret;
    35   for(i=0;i<k;i++)  ret=MAX(ret,w[a]+dptree(son[a],i)+dptree(bro[son[a]],k-1-i));
    36   return dp[a][k]=ret;
    37 }
    38 int main()
    39 {
    40   int i,j,a,b;
    41   while(~scanf("%d%d",&n,&k))
    42   {
    43     for(i=0;i<n;i++)  scanf("%lld",&w[i]);
    44     memset(next,-1,sizeof(next));
    45     memset(first,-1,sizeof(first));
    46     for(i=0;i<n-1;i++)
    47     {
    48       scanf("%d%d",&a,&b);
    49       addEdge(a,b,2*i);
    50       addEdge(b,a,2*i+1);
    51     }
    52     memset(son,-1,sizeof(son));
    53     memset(bro,-1,sizeof(bro));
    54     memset(dp,-1,sizeof(dp));
    55     dfs(0,-1);
    56     ans=0;
    57     for(i=0;i<n;i++)  ans=MAX(ans,dptree(i,k));
    58     printf("%lld\n",ans);
    59   }
    60   return 0;
    61 }
  • 相关阅读:
    try和catch
    获取地址栏参数(E积分项目)
    正则验证,只能输入数字,每四位隔一个空格。
    E积分项目总结(绑卡页 第一步)
    本地存储localStorage用法详解
    python os 模块介绍
    生成器迭代器
    python 魔法方法
    匿名函数
    python自定义函数和内置函数
  • 原文地址:https://www.cnblogs.com/algorithms/p/2481402.html
Copyright © 2011-2022 走看看