1. 程式人生 > >(樹形dp)Computer

(樹形dp)Computer

https://cn.vjudge.net/contest/264707#problem/C
A school bought the first computer some time ago(so this computer’s id is 1). During the recent years the school bought N-1 new computers. Each new computer was connected to one of settled earlier. Managers of school are anxious about slow functioning of the net and want to know the maximum distance Si for which i-th computer needs to send signal (i.e. length of cable to the most distant computer). You need to provide this information.
in
5
1 1
2 1
3 1
1 1
out
3
2
3
4
4

題意是某個學校開始只有一臺電腦,編號為1,之後不斷購進電腦,並與其它電腦以某個距離相連線,給出電腦總數與連線關係,求出每臺電腦距離最遠的電腦
轉換為樹圖,1就是根節點,就是求每個節點到其它葉子節點的最遠距離
剛開始想的時候有用書上倍增暴力去找他們的最遠點,結果發現每個點有多個節點,這種做法就不行了
正解是樹上兩次dp,一次自下而上求出每個點對其子樹的距離的最大值和次大值,再一次自上而下的對其父節點求距離的最大值和次大值。
每次需要求出最大值和次大值的原因在於,如果該點在父節點的最大值的鏈上,則嘗試用次大值的距離和父節點與該節點的距離之和更新其最值;否則用最大值的鏈和父節點與該點的距離之和去更新其最值。
則我們需要dp[i][2]儲存最值,nxt[i][2]儲存最值路徑
還有記得多組輸入,垃圾vj

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e4 + 4;
vector< pair<int, int> > e[maxn];
int dp[maxn][2], nxt[maxn][2];
//0->max 1->second max
void dfs(int u, int pre) {
    for(auto& x : e[u]) {
        int v = x.first, w = x.second;
        if(v == pre) continue;
        dfs(v, u);
        if(dp[v][0] + w > dp[u][0]) {
            dp[u][1] = dp[u][0];
            nxt[u][1] = nxt[u][0];
            dp[u][0] = dp[v][0] + w;
            nxt[u][0] = v;
        }
        else if(dp[v][0] + w > dp[u][1]) {
            dp[u][1] = dp[v][0] + w;
            nxt[u][1] = v;
        }
    }
}
void dfs2(int u, int pre, int len) {
    if(u != 1) {
        if(nxt[pre][0] == u) {
            if(dp[u][0] < dp[pre][1] + len) {
                dp[u][1] = dp[u][0];
                nxt[u][1] = nxt[u][0];
                dp[u][0] = dp[pre][1] + len;
                nxt[u][0] = pre;
            }
            else if(dp[u][1] < dp[pre][1] + len) {
                dp[u][1] = dp[pre][1] + len;
                nxt[u][1] = pre;
            }
        }
        else {
            if(dp[u][0] < dp[pre][0] + len) {
                dp[u][1] = dp[u][0];
                nxt[u][1] = nxt[u][0];
                dp[u][0] = dp[pre][0] + len;
                nxt[u][0] = pre;
            }
            else if(dp[u][1] < dp[pre][1] + len) {
                dp[u][1] = dp[pre][1] + len;
                nxt[u][1] = pre;
            }
        }
    }
    for(auto& x : e[u]) {
        int v = x.first, w = x.second;
        if(v == pre) continue;
        dfs2(v, u, w);
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n;
    while(cin >> n) {
        for(int i = 1; i <= n; i++) e[i].clear(), dp[i][0] = dp[i][1] = nxt[i][0] = nxt[i][1] = 0;
        for(int i = 2; i <= n; i++) {
            int p, x;
            cin >> p >> x;
            e[p].emplace_back(make_pair(i, x));
            e[i].emplace_back(make_pair(p, x));
        }
        dfs(1, 0);
        dfs2(1, 0, 0);
        for(int i = 1; i <= n; i++)
            printf("%d\n", max(dp[i][0], dp[i][1]));
    }
}