您的位置:首页 > 其它

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

2016-05-19 23:19 387 查看


                   
Tree of Tree

描述

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

Tree Definition

A tree is a connected graph which contains no cycles.

输入

 
There are several test
cases 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 nonnegative
integers, where the k-th integer indicates the weight of k-th node.
The following N - 1 lines describe the tree, each line are two
integers which means there is an edge between these two nodes. All
indices above are zero-base and it is guaranteed that the
description of the tree is correct.

输出

 
One line with a single
integer for each case, which is the total weights of the maximum
subtree.

样例输入
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
struct
node

{

 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 int
max(int a,int b)

{

 return a > b ? a : b;

}
void
read_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(int
curNode,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(int
curNode,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);

 }

}
int
main()

{

// 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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: