ACM:最大子树 动态规划题 toj2676

来源:互联网 发布:麻瓜编程 爬虫 编辑:程序博客网 时间:2024/06/05 14:04

                   Tree of Tree

描述

 

You're given a tree withweights of each node, you need to find the maximum subtree ofspecified size of this tree.

Tree Definition
A tree is a connected graph which contains no cycles.

输入

 

There are several testcases in the input.

The first line of each case are two integers N(1<= N <= 100), K(1 <= K<= N), where N is the number of nodes of this tree,and K is the subtree's size, followed by a line with N nonnegativeintegers, where the k-th integer indicates the weight of k-th node.The following N - 1 lines describe the tree, each line are twointegers which means there is an edge between these two nodes. Allindices above are zero-base and it is guaranteed that thedescription of the tree is correct.

输出

 

One line with a singleinteger for each case, which is the total weights of the maximumsubtree.

样例输入

3 1
10 20 30
0 1
0 2
3 2
10 20 30
0 1
0 2

样例输出

30
40

 

题意: 给你一棵树,每个节点有一个相应的权值. 并且给定确定的子树节点个数, 求出最大的子树.

 

解题思路:

              1. 一开始的思路只想到暴力深搜枚举, 不断更新最大值.

              2. 发现深搜时, 深度过大递归树无法完成任务.

              3. 网上看题解发现, 是dfs + dp规划.

              4. 动态规划:

               问题分析:

                      (1). 找状态转移的状态:  dp[curNode][k]: 表示当前第curNode个节点,到子树有k个

                              节点的最大权值.

                       (2).状态转移方程: dp[curNode][k] = max(dp[curNode][k], dp[curNode][j] +dp[curNode][k-j]

 

代码:

#include<cstdio>
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
#define MAX 205

structnode
{
 int u, v;
 int next;
}edges[MAX];

int w[MAX],first[MAX];
int n, k;
int maxsize;
int num;
int dp[MAX][MAX];  //dp[i][k]:表示第i个节点开始的k个节点最大权值

inline intmax(int a,int b)
{
 return a > b ? a : b;
}

voidread_graph()
{
 maxsize = 0;
 memset(first,-1,sizeof(first));
 memset(edges,0,sizeof(edges));
 num = 0;
 int i;
 for(i = 0; i < n; ++i)
 {
  scanf("%d",&w[i]);
 }

 int u, v;
 for(i = 0; i < n-1; ++i)
 {
  scanf("%d%d",&u,&v);
  edges[num].u = u;
  edges[num].v = v;
  edges[num].next =first[u];
  first[u] = num++;
 }
}

void find(intcurNode,int child)
{
 for(int i = k; i >= 1; --i)
 {
  for(int j = i; j>= 1; --j)
  {
   dp[curNode][i]= max(dp[curNode][i] , dp[curNode][j] + dp[child][i-j]);//更新当前节点curNode, i个子节点的最大权值
  }
 }
}

void dfs(intcurNode,int parent)
{
 dp[curNode][1] = w[curNode];
 for(int e = first[curNode]; e != -1; e =edges[e].next)
 {
  int child = edges[e].v;
  if(child == parent)
   continue;
  dfs(child,curNode);
  find(curNode,child);
 }
}

intmain()
{
// freopen("input.txt","r",stdin);
 while(scanf("%d%d",&n,&k) != EOF)
 {
  read_graph();

  memset(dp,0,sizeof(dp));
  dfs(0,0);

  maxsize =-1;
  for(int i = 0; i< n; ++i)
   maxsize =max(maxsize,dp[i][k]);

  printf("%d\n",maxsize);
 }
 return 0;
}

0 0