HDU 5534 Partial Tree 【完全背包+思维】

来源:互联网 发布:淘宝怎么提升排名靠前 编辑:程序博客网 时间:2024/06/05 03:30


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 lacksofn−1 edges. You wantto complete this tree by addingn−1 edges.There must be exactly one path between any two nodes after adding. As you know,there arenn−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 isf(d), wheref is a predefinedfunction andd 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 integersf(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;}



原创粉丝点击