(树形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]));
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_40588429/article/details/84753850