您的位置:首页 > 其它

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

2017-09-08 09:05 477 查看

Partial Tree

[b]Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)

Total Submission(s): 1476    Accepted Submission(s): 739
[/b]

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个节点的树,但是还没有连边,现在要你去连边。然后对于一棵树,它的权值的计算与每个点的度有关,如果某个点的度是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 10100
using namespace std;

LL dp
,f
;
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: