zoukankan      html  css  js  c++  java
  • 树的直径(最长路)

    树间距离最长的两点所形成的路径叫做树的最长路

    设这条路为s->t.

    很容易想到的方法是以每个点为起点当做s,然后dfs求t。  时间复杂度是O(V*(V+E))

    但有更简单的方法是,以任意点u进行dfs找到最远点,这个最远点为s或t,然后以这个最远点进行dfs,即可找到最长路

    那么如何证明以任意点u进行dfs找到最远点,这个最远点为s或t呢??

    为了写证明更简洁,我们设这点最远点为t

    证明如下:

    (1)点u为最长路s->t上的点,那么以u为起点搜到的最远点肯定为s或t,如果不是,那么很显然,s->t不是最长路

    (2)点u不是最长路上的点,那么又分为两种情况

      a:以点u搜到的最远点形成的路径与s->t有交点x,那么这条路的形成分为两个步骤,从u走到x,再从x搜最远点(又回到了第一种情况),

      b:以点u搜到的最远点为T的路径与s->t没有交点,又因为图是联通的,那么可以从u走出一条路,该路与s->t有交点k。那么如图

      

    那么 dist(u,T) > dist(u,k) + dist(k,t)

    -->dist(u,T) > dist(k,t)

    -->dist(u,T) + dist(s,k)+dist(u,k) > dist(k,t) + dist(s,k) = dist(s,t)

    那么最长路就变成了dist(u,T) + dist(s,k)+dist(u,k)。与假设矛盾

    所以又上面的证明可知,

    以任意点u进行dfs找到最远点,这个最远点为s或t(以任意点出发的最长路与树的最长路一定有交点)

     http://lx.lanqiao.org/problem.page?gpid=T32

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <vector>
     4 using namespace std;
     5 const int N = 10000 + 10;
     6 struct node
     7 {
     8     int v,next,cost;
     9 }g[N*2];
    10 int e,head[N];
    11 bool vis[N];
    12 void addEdge(int u, int v, int cost)
    13 {
    14     g[e].v = v;
    15     g[e].cost = cost;
    16     g[e].next = head[u];
    17     head[u] = e++;
    18 }
    19 int maxDist,index;
    20 void dfs(int u, int dist)
    21 {
    22     if(dist > maxDist)
    23     {
    24         maxDist = dist;
    25         index = u;
    26     }    
    27     for(int i=head[u]; i!=-1; i=g[i].next)
    28     {
    29         int v = g[i].v;
    30         if(!vis[v])
    31         {
    32             vis[v] = true;
    33             dfs(v,dist+g[i].cost);
    34             vis[v] = false;
    35         }
    36 
    37     }
    38 }
    39 int main()
    40 {
    41     int n,u,v,c,i;
    42     scanf("%d",&n);
    43     memset(head,-1,sizeof(head));
    44     for(i=1; i<n; ++i)
    45     {
    46         scanf("%d%d%d",&u,&v,&c);
    47         addEdge(u,v,c);
    48         addEdge(v,u,c);
    49     }
    50     memset(vis,0,sizeof(vis));
    51     vis[i] = true;
    52     dfs(i,0);
    53     memset(vis,0,sizeof(vis));
    54     vis[index] = true;
    55     dfs(index,0);
    56     printf("%d
    ",maxDist*10 + (1+maxDist)*maxDist/2);
    57     return 0;
    58 }
    View Code
  • 相关阅读:
    XPOSED优秀模块列表 反射
    XPOSED优秀模块列表 ENABLE CALL RECORDING (三星启用通话录音)
    sp_Rename批量修改数据表的列名
    我的第一个sql server function
    js传递参数时是按照值传递的
    TreeView 绑定到深度未知的数据源
    silverlight中WCF服务定义终结点后可以方便部署
    Jquery常用方法合集,超实用
    sql 触发器 if条件判断
    如何用js判断document里的一个对象是否存在?或是是否有效
  • 原文地址:https://www.cnblogs.com/justPassBy/p/4363362.html
Copyright © 2011-2022 走看看