Codeforces Round #168 (Div. 2)D. Zero Tree(DP,中等难度)
A tree is a graph with n vertices and exactly n?-?1 edges; this graph should meet the following condition: there exists exactly one shortest (by number of edges) path between any pair of its vertices.
A subtree of a tree T is a tree with both vertices and edges as subsets of vertices and edges of T.
You're given a tree with n vertices. Consider its vertices numbered with integers from 1 to n. Additionally an integer is written on every vertex of this tree. Initially the integer written on the i-th vertex is equal to vi. In one move you can apply the following operation:
Calculate the minimum number of moves that is required to make all the integers written on the vertices of the given tree equal to zero.
InputThe first line of the input contains n (1?≤?n?≤?105). Each of the next n?-?1 lines contains two integers ai and bi (1?≤?ai,?bi?≤?n;?ai?≠?bi) indicating there's an edge between vertices ai and bi. It's guaranteed that the input graph is a tree.
The last line of the input contains a list of n space-separated integers v1,?v2,?...,?vn (|vi|?≤?109).
OutputPrint the minimum number of operations needed to solve the task.
Please, do not write the %lld specifier to read or write 64-bit integers in С++. It is preferred to use the cin, cout streams or the %I64d specifier.
Sample test(s) Input 31 2
1 3
1 -1 1 Output 3
一開始題目理解錯誤:“includes the vertex with number 1.”是指結點1而非其上integer為1的結點。
思路是先處理兒子再處理父親。這是因為:設有結點x,x的val變為0所需操作次數x.count = in + de + r,這里in是x因為兒子結點的+1操作
而隨之產生的+1操作的次數(對兒子的操作會傳遞到父親),而de就是-1操作,顯然,in是x的所有兒子中+1次數的最大值,de是所有兒子中-1次
數的最大值。而r是什么?在處理完兒子后確保兒子的val為0,但不保證x的val為0,r就是余下的對x操作的次數:r=x.val+in-de(這些操作是
發生在x和他的父親之間的)。由以上于可見,對x.count的統計能轉化為對其兒子結點的相關信息的統計,故而此前說“先處理兒子后處理父親”。
結點1是最后處理的。
這里還涉及如何保存一個結點的所有兒子的信息的問題,我開始用鄰接表,超時,后來參考別人的代碼才想起來可以用vector。
AC Code:
1 #include <iostream> 2 #include <string> 3 #include <set> 4 #include <map> 5 #include <vector> 6 #include <stack> 7 #include <queue> 8 #include <cmath> 9 #include <cstdio> 10 #include <cstring> 11 #include <algorithm> 12 using namespace std; 13 #define LL long long 14 #define cti const int 15 #define dg(i) cout << "*" << i << endl; 16 17 cti MAXN = 100005; 18 int n; 19 bool vis[MAXN]; 20 LL v[MAXN]; 21 struct Count 22 { 23 LL in; //結點i增1次數 24 LL de; //結點i減1次數 25 }cnt[MAXN]; 26 vector<LL> node[MAXN]; 27 28 Count DP(int i) 29 { 30 vis[i] = true; 31 LL in = 0, de = 0; //in for increse, de for decrese 32 Count t; 33 for(vector<LL>::iterator it = node[i].begin(); it != node[i].end(); it++) 34 { 35 if(vis[*it]) continue; 36 t = DP(*it); 37 if(t.in > in) in = t.in; 38 if(t.de > de) de = t.de; 39 } 40 cnt[i].de = de; 41 cnt[i].in = in; 42 int d = v[i] - cnt[i].de + cnt[i].in; 43 if(d > 0) cnt[i].de += d; 44 else cnt[i].in -= d; 45 return cnt[i]; 46 } 47 48 49 int main() 50 { 51 while(scanf("%d", &n) != EOF) 52 { 53 for(int i = 1; i <= n; i++) 54 { 55 vis[0] = false; 56 while(!node[i].empty()) node[i].pop_back(); 57 } 58 int a, b; 59 for(int i = 1; i < n; i++) 60 { 61 scanf("%d %d", &a, &b); 62 node[a].push_back(b); 63 node[b].push_back(a); 64 } 65 for(int i = 1; i <= n; i++) 66 scanf("%I64d", &v[i]); 67 Count ans = DP(1); 68 printf("%I64d\n", ans.de + ans.in); 69 } 70 return 0; 71 }
?
總結
以上是生活随笔為你收集整理的Codeforces Round #168 (Div. 2)D. Zero Tree(DP,中等难度)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 科技
- 下一篇: 十进制与二进制间的相互转换