zoukankan      html  css  js  c++  java
  • hdu 2196 树形dp

    转自:http://blog.csdn.net/shuangde800

    题目大意:

    求树上所有点到树上另一点的最远距离;

    基本思路:

    把无根树转化成有根树分析,

    对于上面那棵树,要求距结点2的最长距离,那么,就需要知道以2为顶点的子树(蓝色圈起的部分,我们叫它Tree(2)),距顶点2的最远距离L1

    还有知道2的父节点1为根节点的树Tree(1)-Tree(2)部分(即红色圈起部分),距离结点1的最长距离+dist(1,2) = L2,那么最终距离结点2最远的距离就是max{L1,L2}

    f[i][0],表示顶点为i的子树的,距顶点i的最长距离
    f[i][1],表示Tree(i的父节点)-Tree(i)的最长距离+i跟i的父节点距离

    要求所有的f[i][0]很简单,只要先做一次dfs求每个结点到叶子结点的最长距离即可。
    然后要求f[i][1], 可以从父节点递推到子节点,

    假设节点u有n个子节点,分别是v1,v2...vn
    那么
    如果vi不是u最长距离经过的节点,f[vi][1] = dist(vi,u)+max(f[u][0], f[u][1])
    如果vi是u最长距离经过的节点,那么不能选择f[u][0],因为这保存的就是最长距离,要选择Tree(u)第二大距离secondDist,
    可得f[vi][1] = dist(vi, u) + max(secondDist, f[u][1])

    代码如下:

    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<vector>
    
    using namespace std;
    
    typedef long long ll;
    const int inf = 0x3f3f3f3f;
    const double eps = 1e-8;
    const int maxn = 10000+10;
    
    struct Node{
        int v,w;
    };
    vector<Node>adj[maxn];bool vis[maxn];
    int n,m;
    ll f[maxn][2];
    //求f[u][0]
    ll dfs1(int u){
        vis[u]=true;
        f[u][0]=0;
        int sz=adj[u].size();
        for(int i=0;i<sz;i++){
            int v=adj[u][i].v;
            int w=adj[u][i].w;
            if(vis[v]) continue;
            f[u][0]=max(f[u][0],dfs1(v)+w);
        }
        return f[u][0];
    }
    //求f[u][1]
    void dfs2(int u,int fa_w){ vis[u]=true; int max1=0,v1,max2=0,v2; int sz=adj[u].size(); for(int i=0;i<sz;++i){ int v=adj[u][i].v; int w=adj[u][i].w; if(vis[v]) continue; int tmp=f[v][0]+w; if(tmp>max1){ max2=max1;v2=v1; max1=tmp;v1=v; }else if(tmp==max1||tmp>max2){ max2=tmp; v2=v; } } if(u!=1){ int tmp=f[u][1]; int v=-1; if(tmp>max1){ max2=max1;v2=v1; max1=tmp;v1=v; }else if(tmp==max1||tmp>max2){ max2=tmp; v2=v; } } for(int i=0;i<sz;i++){ int v=adj[u][i].v; int w=adj[u][i].w; if(vis[v]){ continue; } if(v==v1){ f[v][1]=max2+w; }else{ f[v][1]=max1+w; }//如果v==v1,说明v1在u的最长距离上,那么v的最长距离就不能用max1,只能用max2; dfs2(v,w); } } int main(){ while(~scanf("%d",&n)&&n){ for(int i=1;i<=n;i++){ adj[i].clear(); } for(int u=2;u<=n;u++){ int v,w; scanf("%d%d",&v,&w); adj[u].push_back((Node){v,w}); adj[v].push_back((Node){u,w}); } memset(f,0,sizeof(f)); memset(vis,0,sizeof(vis)); dfs1(1); memset(vis,0,sizeof(vis)); dfs2(1,0); for(int i=1;i<=n;i++){ printf("%lld ",max(f[i][0],f[i][1])); } } return 0; }
  • 相关阅读:
    react中关于render渲染次数的性能优化
    ES6中六种常用的传出调用方式
    在Vue-cli中得xxx.vue文件中快速生成组件模板
    如何在Vue-cli中关闭ESLint以及关闭部分ESLint验证
    使用ES6删除对象中某些属性
    React中使用遍历
    git commit报错解决,绕过代码检查
    React学习——子组件给父组件传值
    React学习——通过模态框中的表单,学习父子组件之间传值
    学习axios
  • 原文地址:https://www.cnblogs.com/imzscilovecode/p/8392308.html
Copyright © 2011-2022 走看看