51Nod 1405 树的距离之和 (树dp)

题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1405

中文题面不解释了,两次dfs,第一次自下向上,第二次自上向下。

ans[i]表示i节点的答案,cnt[i]表示i节点为root的子树的节点个数,d[i]表示i节点为root的子树的答案。

 1 //#pragma comment(linker, "/STACK:102400000, 102400000")
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <cstdlib>
 5 #include <cstring>
 6 #include <cstdio>
 7 #include <vector>
 8 #include <cmath>
 9 #include <ctime>
10 #include <list>
11 #include <set>
12 #include <map>
13 using namespace std;
14 typedef long long LL;
15 typedef pair <int, int> P;
16 const int N = 1e5 + 5;
17 LL cnt[N], d[N], ans[N], n;
18 vector <int> edge[N];
19 
20 void dfs1(int u, int p) {
21     cnt[u] = 1;
22     d[u] = 0;
23     for(int i = 0; i < edge[u].size(); ++i) {
24         int v = edge[u][i];
25         if(v == p)
26             continue;
27         dfs1(v, u);
28         cnt[u] += cnt[v];
29         d[u] += cnt[v] + d[v];
30     }
31 }
32 
33 void dfs2(int u, int p) {
34     if(p != -1) {
35         ans[u] = (ans[p] - d[u] - cnt[u]) + (n - cnt[u]) + d[u];
36     } else {
37         ans[u] = d[u];
38     }
39     for(int i = 0; i < edge[u].size(); ++i) {
40         int v = edge[u][i];
41         if(v == p)
42             continue;
43         dfs2(v, u);
44     }
45 }
46 
47 int main()
48 {
49     int u, v;
50     while(~scanf("%lld", &n)) {
51         for(int i = 1; i <= n; ++i) {
52             edge[i].clear();
53         }
54         for(int i = 1; i < n; ++i) {
55             scanf("%d %d", &u, &v);
56             edge[u].push_back(v);
57             edge[v].push_back(u);
58         }
59         dfs1(1, -1);
60         dfs2(1, -1);
61         for(int i = 1; i <= n; ++i) {
62             printf("%lld
", ans[i]);
63         }
64     }
65     return 0;
66 }
原文地址:https://www.cnblogs.com/Recoder/p/5893891.html