HDU 4679 Terrorist’s destroy【Tree】

給一棵樹,每條邊上都有一個權值,去掉樹上任意一條邊之後,分成兩個子樹,兩個子樹的最長路與這條邊上的權值相乘,的到一個乘積。問去掉那一條邊可以使這個乘積最小。

首先找到樹上的最長路,那麼刪邊的時候有兩種情況:

1. 這條邊不是最長路上的邊

2. 這條邊是最長路上的邊

對於第一種情況,很容易計算出乘積。

對於第二種情況,只需要計算出被分成的兩個子樹裏面的最長路徑長度即可,這個可以預處理一下。分析可以發現,這種情況下,兩棵子樹的最長路,一定是以整棵樹的最長路的兩個端點爲起始點的,因此只需要預處理出所有點到兩個端點的距離,然後根據刪除的最長路邊求兩顆子樹中的最大值即可。

所有預處理都是dfs……

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
#define N 100010
#define inf 0x7fffffff

bool y[N];
int n, s, t, ds[N], dt[N], ms[N], mt[N], len, id, ans;
struct node {
    int v, w, id;
    node() {}
    node(int _v, int _w, int _id) : v(_v), w(_w), id(_id) {}
};
vector<node> g[N];
void dfs(int now, int fa) {
    int u;
    for (int i=0; i<g[now].size(); i++)
        if ((u = g[now][i].v) != fa) {
            ds[u] = ds[now] + 1;
            dfs(u, now);
        }
}
void dfs2(int now, int fa) {
    int u;
    for (int i=0; i<g[now].size(); i++)
        if ((u = g[now][i].v) != fa) {
            dt[u] = dt[now] + 1;
            dfs2(u, now);
        }
}
void d1(int now, int fa) {
    int u;
    mt[now] = dt[now];
    for (int i=0; i<g[now].size(); i++)
        if ((u = g[now][i].v) != fa) {
            d1(u, now);
            mt[now] = max(mt[now], mt[u]);
        }
}
void d2(int now, int fa) {
    int u;
    ms[now] = ds[now];
    for (int i=0; i<g[now].size(); i++)
        if ((u = g[now][i].v) != fa) {
            d2(u, now);
            ms[now] = max(ms[now], ms[u]);
        }
}
void work(int now, int fa) {
    int u, w;
    for (int i=0; i<g[now].size(); i++)
        if ((u = g[now][i].v) != fa) {
            if (ds[now] + 1 + dt[u] == len)
                w = g[now][i].w * max(ms[now], mt[u]);
            else w = g[now][i].w * len;

            if (w < ans) { ans = w, id = g[now][i].id; }
            else if (w == ans && g[now][i].id < id)
                id = g[now][i].id;
            work(u, now);
        }
}
int main() {
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif
    int size = 20 << 20; // 20MB
    char *p = (char*)malloc(size) + size;
    __asm__("movl %0, %%esp\n" :: "r"(p));

    int T;
    scanf("%d", &T);
    for (int cas=1; cas<=T; cas++) {
        scanf("%d", &n);
        for (int i=0; i<=n; i++) {
            g[i].clear();
            y[i] = false;
        }
        for (int i=1, a, b, c; i<n; i++) {
            scanf("%d%d%d", &a, &b, &c);
            g[a].push_back(node(b, c, i));
            g[b].push_back(node(a, c, i));
        }
        ds[1] = 0;
        dfs(1, 0);
        ds[s=0] = 0; for (int i=1; i<=n; i++) if (ds[i] > ds[s]) s = i;

        ds[s] = 0; dfs(s, 0);
        t = 0; for (int i=1; i<=n; i++) if (ds[i] > ds[t]) t = i;
        len = ds[t];

        dt[t] = 0;
        dfs2(t, 0);

        d1(s, 0); d2(t, 0);

        id = ans = inf;
        work(s, 0);
        printf("Case #%d: %d\n", cas, id);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章