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

    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.

    Hint: the example input is corresponding to this graph. And from the graph, you can see that the computer 4 is farthest one from 1, so S1 = 3. Computer 4 and 5 are the farthest ones from 2, so S2 = 2. Computer 5 is the farthest one from 3, so S3 = 3. we also get S4 = 4, S5 = 4.

    Input
    Input file contains multiple test cases.In each case there is natural number N (N<=10000) in the first line, followed by (N-1) lines with descriptions of computers. i-th line contains two natural numbers - number of computer, to which i-th computer is connected and length of cable used for connection. Total length of cable does not exceed 10^9. Numbers in lines of input are separated by a space.

    Output
    For each case output N lines. i-th line must contain number Si for i-th computer (1<=i<=N).

    Sample Input
    5
    1 1
    2 1
    3 1
    1 1

    Sample Output
    3
    2
    3
    4
    4

    题意:
    给出一棵树,求离每个节点最远的点的距离

    思路:
    把无根树转化成有根树分析。

    对于上面那棵树,要求距结点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<map>
    #include<set>
    #include<queue>
    #include<stack>
    #include<vector>
    #include<math.h>
    #include<cstdio>
    #include<sstream>
    #include<numeric>//STL数值算法头文件
    #include<stdlib.h>
    #include <ctype.h>
    #include<string.h>
    #include<iostream>
    #include<algorithm>
    #include<functional>//模板类头文件
    using namespace std;
    
    const int MAXN = 10010;
    
    struct Node{
        int v, w;
    };
    
    vector<Node>adj[MAXN];
    
    int indeg[MAXN];
    int val[MAXN];
    int n, m;
    int64 f[MAXN][2];
    int vis[MAXN];
    
    int64 dfs1(int u){
       vis[u] = true;
        f[u][0] = 0;
        for(int i=0; i<adj[u].size(); ++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];
    }
    
    
    void dfs2(int u, int fa_w){
        vis[u] = true;
    
        int max1=0, v1, max2=0, v2;
    
        for(int i=0; i<adj[u].size(); ++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<adj[u].size(); ++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;
            }
            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){
                cout << max(f[i][0], f[i][1]) << endl;
            }
        }
    
        return 0;
    }
    
    
    #include<map>
    #include<set>
    #include<queue>
    #include<stack>
    #include<vector>
    #include<math.h>
    #include<cstdio>
    #include<sstream>
    #include<numeric>//STL数值算法头文件
    #include<stdlib.h>
    #include <ctype.h>
    #include<string.h>
    #include<iostream>
    #include<algorithm>
    #include<functional>//模板类头文件
    using namespace std;
    
    typedef long long ll;
    const int maxn=6005;
    const int INF=0x3f3f3f3f;
    
    const int N = 1e4 + 5;
    
    int top;
    int head[N];
    
    struct Edge
    {
        int v,w,next;
    } E[N];
    
    
    void init()
    {
        memset(head,-1,sizeof(head));
        top = 0;
    }
    
    void add_edge(int u,int v,int w)
    {
        E[top].v = v;
        E[top].w = w;
        E[top].next = head[u];
        head[u] = top++;
    }
    
    int dp[N][3];
    
    void dfs1(int u)
    {
        int biggest = 0, bigger = 0;
        for(int i=head[u]; i!=-1; i=E[i].next)
        {
            int v = E[i].v;
            dfs1(v);
            int tmp = dp[v][0]+E[i].w;
            if(biggest <= tmp)
            {
                bigger = biggest;
                biggest = tmp;
            }
            else if(bigger < tmp)
                bigger = tmp;
        }
        dp[u][0] = biggest;
        dp[u][1] = bigger;
    }
    
    void dfs2(int u)
    {
        for(int i=head[u]; i!=-1; i=E[i].next)
        {
            int v = E[i].v;
            dp[v][2] = max(dp[u][2], dp[v][0]+E[i].w==dp[u][0] ? dp[u][1] : dp[u][0]) + E[i].w;
            dfs2(v);
        }
    }
    
    int main()
    {
        int n;
        while(~scanf("%d",&n))
        {
            init();
            for(int v=2; v<=n; v++)
            {
                int u,w;
                scanf("%d%d",&u,&w);
                add_edge(u,v,w);
            }
            dfs1(1);
            dp[1][2] = 0;
            dfs2(1);
            for(int i=1; i<=n; i++)
                printf("%d
    ",max(dp[i][0],dp[i][2]));
        }
        return 0;
    }
  • 相关阅读:
    Linux操作系统定时任务系统 Cron 入门
    ssh命令远程登录
    jQuery 中 attr() 和 prop() 方法的区别
    javascript深入理解js闭包
    怎样使用Markdown
    顺颂商祺
    利用Code128字体将文本转换为code128条形码
    如何看懂Code128条形码
    SSH原理及操作
    ssh 22端口号拒绝
  • 原文地址:https://www.cnblogs.com/nyist-xsk/p/7264811.html
Copyright © 2011-2022 走看看