• 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;
    }

     

  • 相关阅读:
    JAVA动态代理学习
    .Netcore Swagger
    无废话,用.net core mvc 开发一个虽小但五脏俱全的网站
    专为开发者开发的导航网站
    利用webbrowser自动查取地点坐标
    帮你理解学习lambda式
    activeX 打包
    activeX 开发
    提取验证码到winform上webbroswer和axwebbroswer
    存储过程分页的注入问题以及解决
  • 原文地址:https://www.cnblogs.com/-Ackerman/p/12354134.html
Copyright © 2020-2023  润新知