码迷,mamicode.com
首页 > 其他好文 > 详细

[hiho 12]树上的动归

时间:2015-05-05 14:17:45      阅读:128      评论:0      收藏:0      [点我收藏+]

标签:

题目描述

回想一下 hiho 03 和 hiho 04 的 KMP 算法和 Trie 图。

Trie 图其实就是在树上做 KMP。

 

同样地,树上的动归其实就是……在树上做动归。

之前做的动归是在线性表上做的,只有一条路径,树上的动归有多条路径,但这本质上是没有区别的。

 

状态 f[i, j] 含义是以 i  为根的树包含根节点在内不超过 j 个节点的连通分量构成的最大和。

状态转移方程:f[i, j] = max(f[i, j], f[i, j – k] + f[i_child, k]),其中 i_child 表示 i  的子节点。

需要注意的是转移顺序,j 应该从大到小转移:当 i_child 确定,计算 f[i, j] 需要用到 f[i, j – k],此时的 f[i, j – k] 应当是没有使用 i_child 这棵子树上的节点的。

结果的状态表示是 f[1, m]。

 

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

vector<int> tree[105];
int f[105][105];
int n, m;

void dfs(int root_idx, int pa_idx) {
	int len = tree[root_idx].size();
	for (int i = 0; i < len; i++) {
		int sub_idx = tree[root_idx][i];
		if (sub_idx != pa_idx) {
			dfs(sub_idx, root_idx);
			for (int j = m; j > 1; j--) {
				for (int k = 1; k < j; k++) {
					f[root_idx][j] = max(f[root_idx][j], f[root_idx][j - k] + f[sub_idx][k]);
				}
			}
		}
	}
}

int main() {
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		cin >> f[i][1];
	}
	for(int i = 1; i < n; i++) {
		int a, b;
		cin >> a >> b;
		tree[a].push_back(b);
		tree[b].push_back(a);
	}

	dfs(1, 0);
	cout << f[1][m] << endl;

	return 0;
}

[hiho 12]树上的动归

标签:

原文地址:http://www.cnblogs.com/xblade/p/4478850.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!