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\n", ans[i]); 63 } 64 } 65 return 0; 66 }