`
444878909
  • 浏览: 637821 次
文章分类
社区版块
存档分类
最新评论

CF 294E Shaass the Great【Tree】

 
阅读更多

将树的一条边移掉,然后将这条边重新连接两棵子树,使新树:两两点对的距离之和最小。

枚举删掉的边,对每种情况都计算一下,然后取最小值。

对于每种情况,假设左子树的两两点对和为S1,右子树为S2,子树结点个数分别为C1,C2,两个子树到树根的距离和分别为R1,R2,当前枚举的边的权值为w,则整棵树的代价为:

两棵子树的点对和+经过当前边的点对和

S1 + S2 + (C1 + C2)*w + C1*R2 + C2*R1

一棵树如果确定的话,S1和S2都是确定的,不确定的是R1和R2,因此只需要求出R1和R2的最小值。

f[i] 表示以i为根,其他所有结点到i的代价和。则R = min(f[i]), S = sigma(f[i]) / 2;

f[i]的值很容易通过两边遍历求出(具体看代码)。

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
typedef pair<int, int> pii;
typedef long long ll;
#define N 5003
const ll inf = 1ll<<60;

int n, s[N], size;
vector<pii> g[N];
ll d[N], ans, f[N], sum, res, s1, s2, r1, r2, c1, c2;
void dfs1(int now, int fa) {
    int u; ll w;
    s[now] = 1; f[now] = 0;
    for (int i=0; i<g[now].size(); i++)
        if ((u = g[now][i].first) != fa) {
            dfs1(u, now);
            s[now] += s[u];
            w = g[now][i].second;
            f[now] += f[u] + s[u]*w;
        }
}
void dfs2(int now, int fa) {
    int u; ll w;
    sum += f[now], res = min(res, f[now]);

    for (int i=0; i<g[now].size(); i++)
        if ((u = g[now][i].first) != fa) {
            w = g[now][i].second;
            f[u] = f[now] + w*(size-2*s[u]);
            dfs2(u, now);
        }
}
void work(int now, int fa) {
    int u; ll w;
    for (int i=0; i<g[now].size(); i++)
        if ((u = g[now][i].first) != fa) {
            dfs1(u, now); size = c1 = s[u]; sum = 0; res = inf;
            dfs2(u, now); s1 = sum/2; r1 = res;

            dfs1(now, u); size = c2 = s[now]; sum = 0; res = inf;
            dfs2(now, u); s2 = sum/2; r2 = res;

            w = g[now][i].second;
            ans = min(ans, s1+s2+c1*c2*w+c1*r2+c2*r1);

            work(u, now);
        }
}
int main() {
    scanf("%d", &n);
    for (int i=0; i<=n; i++) g[i].clear();

    for (int i=1, a, b, c; i<n; i++) {
        scanf("%d%d%d", &a, &b, &c);
        g[a].push_back(make_pair(b, c));
        g[b].push_back(make_pair(a, c));
    }

    ans = inf;
    work(1, 0);

    cout << ans << endl;
    return 0;
}




分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics