*HDU 2196 - Computer(树形DP)

来源:互联网 发布:mac系统怎么制作铃声 编辑:程序博客网 时间:2024/05/16 16:14

题目:

http://acm.hdu.edu.cn/showproblem.php?pid=2196

题意:

n个点,n-1条边,给出边权。求出每个节点最远的点的距离。

思路:

以1作为树根。

[插入]

如图,要得到节点2的最长距离,距离L1 是节点子树的最远距离,另一个距离L2 是图中的红色部分的最远距离+dis(2,1),结果为max(L1,L2)。

dp【v】【0】:记录节点v的子树的最远距离。此部分dfs1实现。

dp【v】【1】:记录v的父亲节点u 除了节点v的子树 的最远距离 + dis(u,v)。

                              实现方法为由父节点推到子节点。分为两种情况:

                              1. 如果v不是u的最长边上的点,则dp【v】【1】 = dis(u,v)+ max(dp【u】【0】, dp【u】【1】);

                              2. 如果v是u的最长边上的点,则 dp【v】【1】 = dis(u,v)+ max(second_long , dp【u】【1】);

注意答案是long long。

AC.

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>using namespace std;typedef long long ll;const int maxn = 1e4+10;int n;int head[maxn], tot;struct Edge {    int to, next;    ll w;}edge[2*maxn];void addedge(int u, int v, ll w){    edge[tot].to = v;    edge[tot].w = w;    edge[tot].next = head[u];    head[u] = tot++;}ll dp[maxn][2];bool vis[maxn];ll dfs1(int u){    if(dp[u][0]) return dp[u][0];    vis[u] = 1;    for(int i = head[u]; ~i; i = edge[i].next) {        int v = edge[i].to;        ll w = edge[i].w;        if(vis[v]) continue;        dp[u][0] = max(dp[u][0], dfs1(v) + w);    }    return dp[u][0];}void dfs2(int u){    vis[u] = 1;    ll max1 = 0, max2 = 0, w, tmp;    int v, v1, v2;    for(int i = head[u]; ~i; i = edge[i].next) {        v = edge[i].to; w = edge[i].w;        if(vis[v]) continue;        tmp = dp[v][0] + w;        if(tmp > max1) {            max2 = max1; max1 = tmp;            v1 = v;        }        else if(max1 == tmp || tmp > max2) max2 = tmp;    }    if(u != 1) {        tmp = dp[u][1];        v = -1;        if(tmp > max1) {            max2 = max1; max1 = tmp;            v1 = v;        }        else if(max1 == tmp || tmp > max2) max2 = tmp;    }    for(int i = head[u]; ~i; i = edge[i].next) {        v = edge[i].to;        w = edge[i].w;        if(vis[v]) continue;        if(v == v1) dp[v][1] = max2 + w;        else dp[v][1] = max1 + w;        dfs2(v);    }}void init(){    tot = 0;    memset(head, -1, sizeof(head));    memset(dp, 0, sizeof(dp));}int main(){    //freopen("in", "r", stdin);    while(~scanf("%d", &n)) {        init();        for(int i = 2; i <= n; ++i) {            int u;            ll w;            scanf("%d%I64d", &u, &w);            addedge(u, i, w);            addedge(i, u, w);        }        memset(vis, 0, sizeof(vis));        dfs1(1);        memset(vis, 0, sizeof(vis));        dfs2(1);        for(int i = 1; i <= n; ++i) {            cout<<max(dp[i][0], dp[i][1])<<endl;        }    }    return 0;}




0 0
原创粉丝点击