HDU 5534 Partial Tree (变形完全背包 好题)

来源:互联网 发布:netsh绑定mac 编辑:程序博客网 时间:2024/06/05 05:15


Partial Tree

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)

Total Submission(s): 462    Accepted Submission(s): 236

Problem Description
In mathematics, and more specifically in graph theory, a tree is an undirected graph in which any two nodes are connected by exactly one path. In other words, any connected graph without simple cycles is a tree.
You find a partial tree on the way home. This tree has n nodes but lacks of n1 edges. You want to complete this tree by adding n1 edges. There must be exactly one path between any two nodes after adding. As you know, there arenn2 ways to complete this tree, and you want to make the completed tree as cool as possible. The coolness of a tree is the sum of coolness of its nodes. The coolness of a node isf(d), where f is a predefined function and d is the degree of this node. What's the maximum coolness of the completed tree?
 
Input
The first line contains an integerT indicating the total number of test cases.
Each test case starts with an integer n in one line,
then one line with n1 integers f(1),f(2),,f(n1).

1T2015
2n2015
0f(i)10000
There are at most 10 test cases with n>100.
 
Output
For each test case, please output the maximum coolness of the completed tree in one line.
 
Sample Input
232 145 1 4
 
Sample Output
519
 
Source
2015ACM/ICPC亚洲区长春站-重现赛(感谢东北师大)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5534

题目大意:构造一棵树,已知度为i的点的值为f[i],现在求怎么构造这个树可以使总的数值最大,求最大的数值

题目分析:长春银牌题,这题第一反应是二维n3方的背包,显然做不了,一棵n个点的树的总度数为2n-2,并且每个点的度数至少为1,因此我们可以先给每个点一个度为1的值,总值即n*f[1],然后对剩下的n-2的度做完全背包(dp[i]表示用了i度能得到的最大价值),再分配的时候每个点已经有了一个度,要变换一下度值关系,而且dp要初始化为负无穷,因为变换后的f可能小于0(比如度为2的点的权值比度为1的小)
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;int const MAX = 2200;int const INF = 0x3fffffff;int dp[MAX], f[MAX], n;int main(){int T;scanf("%d", &T);while(T --){int n;scanf("%d", &n);for(int i = 0; i <= n; i++)dp[i] = -INF;for(int i = 1; i <= n - 1; i++)scanf("%d", &f[i]);int val1 = n * f[1];for(int i = 2; i <= n - 1; i++)f[i] -= f[1];for(int i = 1; i <= n - 2; i++)f[i] = f[i + 1];dp[0] = 0;for(int i = 1; i <= n - 2; i++)for(int j = i; j <= n - 2; j++)dp[j] = max(dp[j], dp[j - i] + f[i]);printf("%d\n", dp[n - 2] + val1);}}


 

0 0
原创粉丝点击