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 }
原文地址:https://www.cnblogs.com/algorithms/p/2481402.html