hdu 2196求樹上每個點各自的最遠距離(樹形dp)

題目鏈接

  • 記 f[u] 爲節點 u 第一步向兒子方向走的最遠距離
  • 記 g[u] 爲節點 u 第一步向父親方向走的最遠距離
  • 記 fa[u] 爲節點 u 的父親節點的編號
  • f[u] = max{f[v] + w(u, v)} ,v是u的兒子
  • g[u] = w(u, fa[u]) + max{g[p[u]], f[v] + w(fa[u], v)}, v 是 u 的兄弟
  • 所以要做兩邊dfs,先求出f再求出g。
  • 最後節點 u 的最遠距離即爲max{f[u], g[u]}。
#include <bits/stdc++.h>

using namespace std;

const int maxn = (int)1e4+100;
int n, f[maxn], g[maxn], fa[maxn];
vector< pair<int, int> > G[maxn];

void init(int n) {
    memset(f, 0, sizeof(f));
    memset(g, 0, sizeof(g));
    memset(fa, 0, sizeof(fa));
    for (int i = 1; i <= n; ++i) G[i].clear();  //!!
}
void dfs(int x, int par) {
    fa[x] = par;
    for (pair<int, int> pii : G[x]) {
        int to = pii.first;
        if (to == par) continue;
        dfs(to, x);
        f[x] = max(f[x], f[to] + pii.second);
    }
}
void dfs2(int x, int par) {
    int temp = 0;
    g[x] = g[par];
    for (pair<int, int> pii : G[par]) {
        int to = pii.first;
        if (to == fa[par]) continue;
        if (to == x) temp = pii.second;
        else {
            g[x] = max(g[x], f[to] + pii.second);
        }
    }
    g[x] += temp;
    for (pair<int, int> pii : G[x]) {
        int to = pii.first;
        if (to == par) continue;
        dfs2(to, x);
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.precision(10);
    cout << fixed;
#ifdef LOCAL_DEFINE
    freopen("input.txt", "r", stdin);
#endif

    while (cin >> n) {
        init(n);
        for (int i = 2; i <= n; ++i) {
            int u, val;
            cin >> u >> val;
            G[i].emplace_back(make_pair(u, val));
            G[u].emplace_back(make_pair(i, val));
        }
        dfs(1, 0);
        dfs2(1, 0);
        for (int i = 1; i <= n; ++i) {
            cout << max(f[i], g[i]) << '\n';
        }
    }

#ifdef LOCAL_DEFINE
    cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
    return 0;
}

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