Partial Tree
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 578 Accepted Submission(s): 286
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 are
nn−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 is
f(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
Sample Output
Source
2015ACM/ICPC亚洲区长春站-重现赛(感谢东北师大)
题目大意:告诉你有n各结点,f(i)表示度为i的结点的cool值,现在你需要做的就是加n-1条边,构成一棵树,并使得这棵树的每个结点的cool值之和,即coolness最大,输出最大的coolness。
解体思路:这题如果不看人家写的,我想不到用完全背包。是一道好题,值得好好研究研究。
一棵树,n个结点,则度的总和为2*(n-1).每一个结点至少有1个度,则首先给每个结点一个度,剩下2*(n-1)-n就在这n个结点中随机分配,得到一个cooldness最大的分配方式。可以看成完全背包问题
代码如下:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int f[2020];
int dp[2020];//dp[i]表示增加i个度所得到的coolness值
int main(){
int t,n,v,w,i,j;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(i=1;i<n;i++){
scanf("%d",&f[i]);
}
v=2*(n-1)-n;//每一个结点至少有1个结点,最多有1+n-2个结点
memset(dp,0,sizeof(dp));
dp[0]=n*f[1];//初始化 ,即一开始为每个结点只有一个度
for(i=2;i<n;i++){
for(j=i-1;j<=v;j++)//v相当于背包容量,每一i物品的花费是i-1,价值是f[i]-f[1]
dp[j]=max(dp[j],dp[j-i+1]+f[i]-f[1]);//减去f[1],因为每一个点已经度为1了
}
printf("%d\n",dp[v]);
}
return 0;
}