树形DP Gym 100496H House of Representatives

 

题目传送门

 1 /*  2  题意:寻找一个根节点,求min f(u) = ∑ρ(v, u) * p(v)。ρ(v, u)是u到v的距离,p(v)是v点的权值  3  树形DP:先从1出发遍历第一次,sum[u]计算u到所有子节点v的路径权值(之后的点路径有叠加,所以先把路径权值加后*w),  4  计算f[u](缺少u节点以上的信息)。然后再遍历一遍,之前是DFS从下往上逆推,现在是顺推,把u节点以上的信息加上  5  dp的部分不是很多,两个DFS函数想了很久,还是没完全理解:(  6 */  7 #include <cstdio>  8 #include <cstring>  9 #include <algorithm> 10 #include <vector> 11 using namespace std; 12 13 typedef long long ll; 14 const int MAXN = 1e5 + 10; 15 const int INF = 0x3f3f3f3f; 16 int p[MAXN]; 17 ll f[MAXN]; 18 ll sum[MAXN]; 19 vector<pair<int, int> > G[MAXN]; 20 21 void DFS1(int u, int rt) 22 { 23 f[u] = 0; sum[u] = p[u]; 24 for (int i=0; i<G[u].size (); ++i) 25  { 26 int v = G[u][i].first; int w = G[u][i].second; 27 if (v == rt) continue; 28  DFS1 (v, u); 29 f[u] += f[v] + sum[v] * w; sum[u] += sum[v]; 30  } 31 } 32 33 void DFS2(int u, int rt) 34 { 35 for (int i=0; i<G[u].size (); ++i) 36  { 37 int v = G[u][i].first; int w = G[u][i].second; 38 if (v == rtGym 100496H House of Representatives) continue; 39 f[v] = f[u] - sum[v] * w + (sum[u] - sum[v]) * w; 40 sum[v] = sum[u]; 41  DFS2 (v, u); 42  } 43 } 44 45 int main(void) //Gym 100496H House of Representatives 46 { 47 // freopen ("H.in", "r", stdin); 48 freopen ("house.in", "r", stdin); 49 freopen ("house.out", "w", stdout); 50 51 int n; 52 while (scanf ("%d", &n) == 1) 53  { 54 for (int i=1; i<=n; ++i) scanf ("%d", &p[i]); 55 for (int i=1; i<=n; ++i) G[i].clear (); 56 57 for (int i=1; i<=n-1; ++i) 58  { 59 int u, v, w; scanf ("%d%d%d", &u, &v, &w); 60  G[u].push_back (make_pair (v, w)); 61  G[v].push_back (make_pair (u, w)); 62  } 63 64 DFS1 (1, -1); DFS2 (1, -1); 65 66 int p = 1; 67 for (int i=2; i<=n; ++i) 68  { 69 if (f[i] < f[p]) p = i; 70  } 71 72 printf ("%d %I64d\n", p, f[p]); 73  } 74 75 return 0; 76 }

 

你可能感兴趣的:(res)