您的位置:首页 > 其它

HDU 5534 Partial Tree (完全背包)

2016-10-04 19:50 323 查看

Partial Tree

Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 262144/262144K (Java/Other)
Total Submission(s) : 2   Accepted Submission(s) : 0

Font: Times New Roman | Verdana | Georgia

Font Size: ← →

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 n−1
edges. You want to complete this tree by adding n−1
edges. There must be exactly one path between any two nodes after adding. As you know, there arenn−2
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 integer
T
indicating the total number of test cases.

Each test case starts with an integer n
in one line,

then one line with n−1
integers f(1),f(2),…,f(n−1).

1≤T≤2015
2≤n≤2015
0≤f(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

2
3
2 1
4
5 1 4


Sample Output

5
19


Source

2015ACM/ICPC亚洲区长春站-重现赛(感谢东北师大) 

题意:给定一棵树中每个度数所对应的权值以及树的结点数,求该树的最大权值。
思路:想到要构造一棵n结点的树,结点的总度数应为2n-2,其中肯定要有度数为1的结点,之后就不了了之了。本来想用贪心,但发现各个结点的度数其实是会相互牵制的。最后看了题解发现用完全背包很巧妙。首先令每个结点度数都为1,之后还差n-2度数,将n-2作为背包中的容量限制,每个结点增加的度数可以从1到n-2。
注意转移方程dp[i]=max(dp[i],dp[i-j]+v[j+1]-v[1]),其中dp[i]为凑够i度数的最大权值。最后结果为dp[n-2]+v[1]*n,因为之前初始化没有+v[1],但是在动规的过程中每次减去了v[1],所以最后要补回来。
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
#include <math.h>
using namespace std;
#define INF 999999
int v[2016];
int dp[2016];

int main(){

int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
for(int i=1;i<n;i++)
scanf("%d",&v[i]);
for(int i=1;i<=n-2;i++){
dp[i]=-INF;
}
dp[0]=0;
int m=n-2;
for(int i=1;i<=m;i++){
for(int j=1;j<n-1;j++){
if(j<=i)
dp[i]=max(dp[i],dp[i-j]+v[j+1]-v[1]);
}
}
printf("%d\n",dp[m]+n*v[1]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: