代码改变世界

Codeforces 294E Shaass the Great

2013-07-23 19:42  bootstar  阅读(357)  评论(0编辑  收藏  举报

树形DP。由于n只有5000,可以直接枚举边。

枚举边,将树分成两个子树,然后从每个子树中选出一个点分别为u,v,那么答案就是:

子树1中任意两点距离总和+子树2中任意两点距离总和+子树1中任意一点到u的距离和*子树2的节点个数+子树2中任意一点到v的距离和*子树1的节点个数+子树1的节点个数*子树2的节点个数*当前枚举边的权值。

当枚举的边一定时,那么要选取的点就是子树中到所有点的距离总和最小的点。对树进行dfs,同时记录子树的节点个数,所有孩子节点到当前根节点的距离总和,以及当前子树中任意两点距离和。然后在进行dfs求解到该子树中所有点距离和最小的点。

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <vector>
 4 #include <algorithm>
 5 using namespace std;
 6 typedef long long LL;
 7 typedef pair <int, int> pii;
 8 #define maxn 5005
 9 #define INF 0x3f3f3f3f3f3f3f3fll
10 
11 int f[maxn], h[maxn], w[maxn];
12 vector<pii> g[maxn];
13 int son[maxn];
14 LL d[maxn], s[maxn];
15 
16 void dfs(int v, int rt){
17     son[v] = 0, d[v] = 0, s[v] = 0;
18     for(int i = 0; i != g[v].size(); i ++){
19         int u = g[v][i].first;
20         if(u==rt) continue;
21         dfs(u, v);
22         s[v] += s[u] + d[u]*son[v] + d[v]*son[u] + (LL)son[u] * son[v] * g[v][i].second;
23         d[v] += d[u] + (LL)son[u] * g[v][i].second;
24         son[v] += son[u];
25     }
26     son[v] ++;
27     s[v] += d[v];
28 }
29 void dfsw(int v, int rt, LL &minn){
30     minn = min(d[v], minn);
31     for(int i = 0; i != g[v].size(); i ++){
32         int u = g[v][i].first;
33         if(u==rt) continue;
34         d[u] = d[u] + (d[v] - d[u] - (LL)son[u]*g[v][i].second) + (LL)(son[v] - son[u])*g[v][i].second;
35         son[u] = son[v];
36         dfsw(u, v, minn);
37     }
38 }
39 int main(){
40     //freopen("test.in", "r", stdin);
41     for(int n; scanf("%d", &n)!=EOF; ){
42         for(int i = 1; i <= n; i ++){
43             g[i].clear();
44         }
45         for(int i = 1, x, y, z; i < n; i ++){
46             scanf("%d%d%d", &x, &y, &z);
47             f[i] = x, h[i] = y, w[i] = z;
48             g[x].push_back(make_pair(y, z));
49             g[y].push_back(make_pair(x, z));
50         }
51         LL ans = INF, minn = INF, sum = 0;
52         for(int i = 1; i < n; i ++){
53             minn = INF;
54             dfs(f[i], h[i]);
55             dfsw(f[i], h[i], minn);
56             sum = 0;
57             sum = (n - son[f[i]]) * minn + s[f[i]];
58             minn = INF;
59             dfs(h[i], f[i]);
60             dfsw(h[i], f[i], minn);
61             sum = sum + (n - son[h[i]]) * minn + s[h[i]] + (LL)son[f[i]]*son[h[i]]*w[i];
62             ans = min(ans, sum);
63         }
64         printf("%I64d\n", ans);
65     }
66     return 0;
67 }
View Code