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 }
时间: 2024-11-05 13:33:26