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 }
View Code

 

转载于:https://www.cnblogs.com/Jstyle-continue/p/6426910.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值