codeforces 743D【数dp】
链接:http://codeforces.com/contest/743/problem/D
题意:
给定n个结点的树的每个结点的权值,让你找到两个不相交的子树的最大权值和;1为根节点;
题解:
首先了解一下子树的概念,百度一下就出来了。考虑以u为根结点的子树的最大权值,两种情况:
1.包含u的时候就是所有子树的权值和tol;
2.不包含u的时候就是某颗权值最大的子树;
这样的话dfs+dp便可以搞到所有以i为根节点的最大权值子树,这个时候再来想想更新答案的事情;
答案肯定是某个结点的最大权值子树+次大权值子树,这样子向上更新到1这个根节点的。
那么很显然,在刚才dfs+dp之后找到某个结点的最大和次大子树即可,如果只有一个子树dp有了答案显然不行,必须至少有两个子树都dp更新过答案;
代码:
1 #include <iostream> 2 #include <algorithm> 3 #include <cstring> 4 #include <cstdio> 5 #include <bitset> 6 #include <vector> 7 #include <queue> 8 #include <stack> 9 #include <cmath> 10 #include <list> 11 #include <set> 12 #include <map> 13 #define rep(i,a,b) for(int i = a;i <= b;++ i) 14 #define per(i,a,b) for(int i = a;i >= b;-- i) 15 #define mem(a,b) memset((a),(b),sizeof((a))) 16 #define FIN freopen("in.txt","r",stdin) 17 #define FOUT freopen("out.txt","w",stdout) 18 #define IO ios_base::sync_with_stdio(0),cin.tie(0) 19 #define mid ((l+r)>>1) 20 #define ls (id<<1) 21 #define rs ((id<<1)|1) 22 #define INFF 0x3f3f3f3f3f3f3f 23 using namespace std; 24 typedef long long LL; 25 typedef pair<int, int> PIR; 26 const int N = 2e5+5; 27 int n, u, v; 28 LL a[N], dp[N], ans; 29 vector <int> G[N]; 30 LL dfs(int u, int pre){ 31 LL sum = a[u], maxn1 = -INFF, maxn2 = -INFF; 32 rep(i, 0, (int)G[u].size()-1){ 33 int v = G[u][i]; 34 if(v == pre) continue; 35 sum += dfs(v, u); 36 if(dp[v] > maxn1) { maxn2 = maxn1; maxn1 = dp[v]; } 37 else if(dp[v] > maxn2) maxn2 = dp[v]; 38 } 39 if(maxn1 != -INFF && maxn2 != -INFF) ans = max(ans, maxn1+maxn2); 40 dp[u] = max(maxn1, sum); 41 return sum; 42 } 43 int main() 44 {IO; 45 //FIN; 46 while(cin >> n){ 47 rep(i, 0, n) G[i].clear(); 48 rep(i, 1, n) cin >> a[i]; 49 rep(i, 1, n-1){ 50 cin >> u >> v; 51 G[u].push_back(v); 52 G[v].push_back(u); 53 } 54 ans = -INFF; 55 mem(dp, 0); 56 dfs(1, -1); 57 if(ans == -INFF) cout << "Impossible" << endl; 58 else cout << ans << endl; 59 } 60 return 0; 61 }