• 树形DP求各点能走到的最远距离


    hdu2196

    Computer

    Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 2903    Accepted Submission(s): 1472


    Problem Description
    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
    题意:

    求一个树中所有节点能到达的最远距离f[i]。要用两个dfs

    分析:

    首先第一个dfs求出所有每个节点i在其子树中的正向最大距离正向次大距离dist[i][0]dist[i][1](如果i节点在子树中最大距离经过了2号儿子,那么次大距离就是不经过2号儿子的最大距离)。并且还要标记longest[i]=j表示节点i在其子树中的最大距离经过了节点j(即ji的一个儿子)。

    由上步我们获得了正向最大距离,正向次大距离和最大距离的儿子节点标记。画图可以知道我们建立的这棵树,i节点的最远距离只有两种选择:i节点所在子树的最大距离,或者i节点连接它的父节点所能到达的最大距离。(即前者往下走,后者先往上走之后很可能也往下走)

    所以我们只要求出反向最大距离dist[i][2](即i节点往它的父节点走所能到达的最大距离)就可以知道i节点在整个树中能走的最大距离了。

    dist[i][2]求法:i节点往它的父节j点走,如果它的父节点的正向最大距离不经过i的话,那么dist[i][2]要不就是它父节点的反向最大距离+W[i][j]要不就是它父节点的正向最大距离+ W[i][j].

    如果它的父节点的正向最大距离经过i的话,那么dist[i][2]要不就是它父节点的反向最大距离+W[i][j]要不就是它父节点的正向次大距离+ W[i][j].

    上面就是dfs2要求的值。最终f[i] = maxdist[i][0]dist[i][2]

    程序:

    #include"stdio.h"
    #include"string.h"
    #include"iostream"
    #define M 100009
    #define inf 99999999
    #define eps 1e-9
    #include"math.h"
    using namespace std;
    struct st
    {
        int u,v,w,next;
    }edge[M*3];
    struct node
    {
        int max1,max2,maxj;
    }p[M];
    int head[M],use[M],t,dis[M],in[M],longest[M];
    void init()
    {
        t=0;
        memset(head,-1,sizeof(head));
    }
    
    void add(int u,int v,int w)
    {
        edge[t].u=u;
        edge[t].v=v;
        edge[t].w=w;
        edge[t].next=head[u];
        head[u]=t++;
    }
    void dfs(int u)//求正向最大距离和正向次大距离
    {
        use[u]=1;
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].v;
            if(!use[v])
            {
                dfs(v);
                int MM=p[v].max1+edge[i].w;
                if(p[u].max1<MM)
                {
                    longest[u]=v;
                    int tt=p[u].max1;
                    p[u].max1=MM;
                    p[u].max2=tt;
                }
                else if(p[u].max2<MM)
                {
                    p[u].max2=MM;
                }
            }
        }
        if(in[u]==1)
            p[u].max1=p[u].max2=0;
    }
    void DFS(int u,int fa)//求反向最大距离
    {
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].v;
            if(fa==v)continue;
            if(v==longest[u])
                p[v].maxj=max(p[u].maxj,p[u].max2)+edge[i].w;
            else
                p[v].maxj=max(p[u].maxj,p[u].max1)+edge[i].w;
            DFS(v,u);
        }
    }
    int main()
    {
        int n,i,j,c;
        while(scanf("%d",&n)!=-1)
        {
            init();
            memset(in,0,sizeof(in));
            for(i=2;i<=n;i++)
            {
                scanf("%d%d",&j,&c);
                add(i,j,c);
                add(j,i,c);
                in[i]++;
                in[j]++;
            }
            memset(p,0,sizeof(p));
            memset(use,0,sizeof(use));
            for(i=1;i<=n;i++)
            {
                if(in[i]>1)
                {
                    dfs(i);
                    DFS(i,-1);
                    break;
                }
            }
            for(i=1;i<=n;i++)
            {
                printf("%d
    ",max(p[i].max1,p[i].maxj));
            }
        }
        return 0;
    }



  • 相关阅读:
    字王20年
    [转]Birdfont 2.10 发布,字体编辑器
    vs2013编译boost库
    c++ 完成端口资料
    获取输入法输入内容及后选项的钩子
    unicode string和ansi string的转换函数及获取程序运行路径的代码
    c++实现输入法窗口自定义的代码
    在固定长方形里产生渐变
    监听某个div或其它标签的大小改变来执行相应的处理
    64位SqlServer通过链接服务器与32位oracle通讯
  • 原文地址:https://www.cnblogs.com/mypsq/p/4348225.html
Copyright © 2020-2023  润新知