HDU 5534 Partial Tree ACM/ICPC 2015 Changchun(完全背包)

来源:互联网 发布:网络运营公司简介 编辑:程序博客网 时间:2024/06/05 07:48

Partial Tree

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 1476    Accepted Submission(s): 739

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 integer T 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亚洲区长春站-重现赛(感谢东北师大)



        有n个节点的树,但是还没有连边,现在要你去连边。然后对于一棵树,它的权值的计算与每个点的度有关,如果某个点的度是i,那么这个点的权值贡献就是f(i),其中f(1)~f(n-1)已经给出,然后问最后权值最大的树权值是多少。

        看到这题的时候,我就感觉,不管怎么建树,只要能够保证每个点的度至少为一,那么总是存在一棵树满足你的度数分配要求。换句话说,我们要做的只是把所有的度分配下去,而且分配与点无关,即把度分为n个部分,每个部分不能为0。n-1条边就对应2n-2个度。

        知道了,度数可以任意分配,我们就可以考虑把每一个f(i)看成一个背包,体积为i、价值为f(i),然后把总的度数看作总空间,最后要求把总空间用完而且总价值最大。这就恰好是一个完全背包问题。但是,存在一个问题,那就是无法保证每个点都被分配到度。即,如果有n个点,然后我最后结果有可能取了两个f(n-1),以为着有两个点分配了n-1个度,而其他点没有分配度数,不满足要求。

        对于这个问题,我们考虑提前先给每个点分配一个度,这样我们剩下的度数就是n-2个。然后,对于这n-2个度数,我们就可以真真正正当作完全背包处理,但是注意,在完全背包的时候,由于每个点已经分配了一个度数,那么原本的f(i)背包,它的体积就要变成i-1,然后价值也要相应的减去f(1),变成f(i)-f(1)。

        然后同一年的长春站,网络赛和现场赛都考了背包问题,但是真正能够做出来的人也不太多。所以说背包问题的变种值得关注,然后网络赛对现场赛也有一定的导向作用。具体见代码:

#include<bits/stdc++>#define LL long long#define INF 1e18#define N 10100using namespace std;LL dp[N],f[N];int n;int main(){    int T_T;    cin>>T_T;    while(T_T--)    {        scanf("%d",&n);        for(int i=1;i<n;i++)            scanf("%d",&f[i]);        for(int i=1;i<=n;i++) dp[i]=-INF;//要把空间用完,所以初始化为负无穷大        dp[0]=n*f[1];//先把所有的节点放上1个度        for(int j=1;j<n-1;j++)            for(int i=j;i<=n-2;i++)                dp[i]=max(dp[i],dp[i-j]+f[j+1]-f[1]);        printf("%I64d\n",dp[n-2]);    }    return 0;}

阅读全文
0 0