Partial Tree
Time Limit: 2000/1000 MS (Java/Others) Memory Limit:262144/262144 K (Java/Others)
Total Submission(s): 1480 Accepted Submission(s): 743
Problem Description
Inmathematics, and more specifically in graph theory, a tree is an undirectedgraph 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 lacksof
n−1 edges. You wantto 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 tocomplete this tree, and you want to make the completed tree as cool aspossible.
The coolness of a tree is the sum of coolness of its nodes. Thecoolness of a node is
f(d), where
f is a predefinedfunction and
d isthe 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 testcases.
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 testcases with n>100.
Output
For each test case, please output the maximum coolness of the completed tree in oneline.
Sample Input
2
3
2 1
4
5 1 4
Sample Output
5
19
【题意】
给出n,现在需要你连(n-1)条边使之构成一棵生成树,并给出一个函数f(d)表示度数为d的点的价值,问构造后所有点价值总和的最大值。
【思路】
先给出一个结论,n个节点的生成树所有点的度数总和为2*(n-2)。
那现在我们要做的便是把这2*(n-2)个度数分给n个点,求价值和最大值。
很容易联想到完全背包,可以这样转化:现在有(n-1)个物品,每个物品有一个重量和价值,现在需要你从中选出正好n件物品(可以重复选),且重量和正好为2*(n-1),求物品价值和最大值。
但这样去做由于还要加上一层关于物品件数的循环,复杂度就比较高了。我们需要考虑优化。
我们可以将每个节点先分配一个度,然后剩下(n-2)个度就可以随意分配,而没有个数限制了。
这样的话,就转化成了一个简单的一维完全背包问题了。
但要注意的是每个度数的价值应该转化为它与度数为1的价值的差值再注意下初始化就没问题了。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define mst(a,b) memset((a),(b),sizeof(a))
#define rush() int T;scanf("%d",&T);while(T--)
typedef long long ll;
const int maxn = 2020;
const ll mod = 1e9+7;
const int INF = 0x3f3f3f3f;
const double eps = 1e-9;
int val[maxn];
int dp[maxn*2];
int main()
{
int n;
rush()
{
scanf("%d",&n);
for(int i=0;i<n-1;i++)
{
scanf("%d",&val[i]);
if(i!=0) val[i]-=val[0];
}
mst(dp,-1);
dp[0]=n*val[0];
int V=n-2;
for(int i=1;i<n;i++)
for(int j=i;j<=V;j++)
{
dp[j]=max(dp[j],dp[j-i]+val[i]);
}
printf("%d\n",dp[V]);
}
return 0;
}