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 }

 

你可能感兴趣的:(tree)