Computer (求每个点的树上最远距离)

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2196

思路:

我们定义f【i】表示编号为i的节点第一步向儿子方向走的最远距离
    g【i】表示编号为i的节点第一步向父亲方向走的最远距离
    p【i】表示编号为i的节点的父亲节点编号
    w(a,b)表示编号a节点到编号b节点的距离,a和b是一条边连接的,即边权
用2个dfs求出这三个数组
递推式:f【u】=max(f【v】,w(u,v))//v是u的孩子
    g【u】=w(u,p【u】)+max(g【p【u】】,f【v】+w(p【u】,u))//v是u的兄弟
两个递推式在下面讲解
对于第i个节点,答案就是max(f【i】,g【i】)
因为对一个节点来说,它的第一步只能是向孩子方向走(可能有多个孩子)或者向父亲方向走

往孩子方向走的转移方程很好列

往父亲方向走:

分情况: 1、父亲的父亲 -> 父亲 -> 当前节点

    2、当前节点的兄弟 -> 父亲 -> 当前节点

#include <iostream>
#include <algorithm>
#include <string>
#include <string.h>
#include <vector>
#include <map>
#include <stack>
#include <set>
#include <queue>
#include <math.h>
#include <cstdio>
#include <iomanip>
#include <time.h>
#include <bitset>
#include <cmath>

#define LL long long
#define INF 0x3f3f3f3f
#define ls nod<<1
#define rs (nod<<1)+1

const double eps = 1e-10;
const int maxn = 1e4 + 10;
const LL mod = 1e9 + 7;

int sgn(double a){return a < -eps ? -1 : a < eps ? 0 : 1;}
using namespace std;

struct edge {
    int v,nxt,w;
}e[maxn<<1];

int head[maxn];
int cnt;
int f[maxn],g[maxn];
int p[maxn];

inline void add_edge(int u,int v,int w) {
    e[++cnt].v = v;
    e[cnt].w = w;
    e[cnt].nxt = head[u];
    head[u] = cnt;
}

inline void dfs1(int x,int fa) {
    for (int i = head[x];~i;i = e[i].nxt) {
        int v = e[i].v;
        //int w = e[i].w;
        if (v == fa)
            continue;
        dfs1(v,x);
        p[v] = x;
        f[x] = max(f[x],f[v]+e[i].w);
    }
}

inline void dfs2(int x,int fa) {
    g[x] = g[fa];
    int t = 0;
    for (int i = head[fa];~i;i = e[i].nxt) {
        int v = e[i].v;
        //int w = e[i].w;
        if (v == p[fa])
            continue;
        if (v == x)
            t = e[i].w;
        else
            g[x] = max(g[x],f[v]+e[i].w);
    }
    g[x] += t;
    for (int i = head[x];~i;i = e[i].nxt) {
        int v = e[i].v;
        if (v == fa)
            continue;
        dfs2(v,x);
    }
}

int main() {
    int n;
    while (cin >> n) {
        memset(head,-1, sizeof(head));
        memset(f,0, sizeof(f));
        memset(g,0, sizeof(g));
        memset(p,0, sizeof(p));
        cnt = 0;
        for (int i = 2;i <= n;i++) {
            int u,v,val;
            cin >> v >> val;
            u = i;
            add_edge(u,v,val);
            add_edge(v,u,val);
        }
        dfs1(1,0);
        dfs2(1,0);
        for (int i = 1;i <= n;i++)
            cout << max(f[i],g[i]) << endl;
    }
    return 0;
}

 

猜你喜欢

转载自www.cnblogs.com/-Ackerman/p/12354134.html