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;
}
相关文章推荐
- ACM: 数论题 toj 1721
- ACM: 序列中找最小逆序对 杂题 TOJ…
- mapReduce概念及用法
- ACM: 简单最小生成树 图论题 poj 1…
- ACM: spfa+dfs 图论题 poj 2679
- 图论: 最大流
- ACM: 最大流 图论题 poj 1797
- 线程的常用方法
- ACM: 差分约束 图论题 poj 2983 sp…
- ACM: 二分图最大匹配 hdu 2063
- 数据
- ACM: 二分法 数论题 poj 1905
- ZOJ的轻松ACMER语录.. 狗一样的学…
- ACM: spfa求解 图论题 (对差分约束…
- ACM: 最小费用用最大流 图论题 poj…
- ACM: K次最小费用最大流 图论题 po…
- ACM: 哈希暴力求解 哈希题 poj 184…
- ACM: 最小费用最大流 图论题 poj 2…
- 理解并解决GBK转UTF-8奇数中文乱码(转)
- HDU 2098 分拆素数和