1. 程式人生 > >5534 Partial Tree (完全揹包,物品價值包含負數)

5534 Partial Tree (完全揹包,物品價值包含負數)

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

2
3
2 1
4
5 1 4

Sample Output

5
19

題解:

因為n-1條邊要連線所有的點,所以我們可以先讓每條邊與一個點一對一連線,那麼我們得到(n-1)個度為一的點,剩下一個度為0的是根節點,然後我們讓一條邊與根節點相連,那麼現在n個點的度都為一,因為所有邊共產生2*(n-1)度所以剩下(n-2)度,所以問題轉化成把(n-2)個度分給n個點,使得結果的f(d)和最大。

這明顯是一個完全揹包問題了。可以把度數想成weight,f(d)想成value,(n-2)為揹包最大容量,那麼這就是一個基礎的完全揹包放東西模板。

注意這裡d 和 f(d)都為原值與1和f(1)的差值,也因此會有負數。

程式碼:

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int MAXN = 2020;
const long long INF = 0x3f3f3f3f3f3f3f3f;

struct D{
	long long f,d;
}board[MAXN];

long long dp[MAXN*2];

int main(){	
	
	int T,N;
	scanf("%d",&T);
	while(T--){
		memset(dp,-INF,sizeof dp);
		scanf("%d",&N);
		scanf("%lld",&board[1].f);
		board[1].d = 1;
		for(int i=2 ; i<N ; ++i){
			long long t;
			scanf("%lld",&t);
			board[i].f = t - board[1].f;
			board[i].d = i-1;
		}
		dp[0] = 0;
		long long re = N*board[1].f;
		for(int i=2 ; i<N ; ++i){
	        for(int j=board[i].d ; j<=N-2 ; ++j){
	            if(dp[j-board[i].d] != -INF)dp[j] = max(dp[j],dp[j-board[i].d]+board[i].f);   
	        }
	    }
		printf("%lld\n",re+dp[N-2]);
	}
	
	return 0;
}