連接:http://codeforces.com/contest/743/problem/Dios
題意:ide
給定n個結點的樹的每一個結點的權值,讓你找到兩個不相交的子樹的最大權值和;1爲根節點;spa
題解:code
首先了解一會兒樹的概念,百度一下就出來了。考慮以u爲根結點的子樹的最大權值,兩種狀況:blog
1.包含u的時候就是全部子樹的權值和tol;ci
2.不包含u的時候就是某顆權值最大的子樹;string
這樣的話dfs+dp即可以搞到全部以i爲根節點的最大權值子樹,這個時候再來想一想更新答案的事情;it
答案確定是某個結點的最大權值子樹+次大權值子樹,這樣子向上更新到1這個根節點的。io
那麼很顯然,在剛纔dfs+dp以後找到某個結點的最大和次大子樹便可,若是隻有一個子樹dp有了答案顯然不行,必須至少有兩個子樹都dp更新過答案;event
代碼:
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 }