树的直径

149 阅读2分钟

树的直径:树上最长的简单路径。

算法思想:

1.dfs

通过两遍dfs,第1遍dfs,从任意点P出发,寻找离它最远的点Q 。第2遍dfs,从Q出发,找离它最远的点W。QW就是树的一条直径

2.树形dp

找到每个根节点的最长长度和次长长度,因为最长长度一定会经过某一个根节点

参考文章

juejin.cn/post/684490…

zhuanlan.zhihu.com/p/115966044

两种算法的代码实现

1.dfs

func maxDistance(relations [][]interface{}) int {
   edges := make(map[interface{}]map[interface{}]int, 0)
   for _, relation := range relations {
      u, v, w := relation[0], relation[1], relation[2].(int)
      if _, ok := edges[u]; !ok {
         edges[u] = make(map[interface{}]int, 0)
      }
      edges[u][v] = w
      if _, ok := edges[v]; !ok {
         edges[v] = make(map[interface{}]int, 0)
      }
      edges[v][u] = w
   }

   var dfs func(x interface{}, vis map[interface{}]int) (interface{}, int)
   dfs = func(x interface{}, vis map[interface{}]int) (interface{}, int) {
      _, ok := vis[x]
      if ok {
         return x, vis[x]
      }

      retPoint := x
      retD := 0
      vis[x] = retD
      for v, w := range edges[x] {
         if _, ok := vis[v]; !ok {
            q, tmp := dfs(v, vis)
            if tmp+w > retD {
               retPoint = q
               retD = tmp + w
            }
         }
      }

      vis[x] = retD
      return retPoint, retD
   }

   var q interface{}
   if len(relations) > 0 {
      u := relations[0][0]
      vis := make(map[interface{}]int, 0)
      q, _ = dfs(u, vis)
   }

   vis := make(map[interface{}]int, 0)
   p, ret := dfs(q, vis)
   fmt.Println("point:", q, p)
   fmt.Println("distance:", ret)
   return ret
}

2.树形dp

func maxDistance1(relations [][]interface{}) int {
   edges := make(map[interface{}]map[interface{}]int, 0)
   for _, relation := range relations {
      u, v, w := relation[0], relation[1], relation[2].(int)
      if _, ok := edges[u]; !ok {
         edges[u] = make(map[interface{}]int, 0)
      }
      edges[u][v] = w
      if _, ok := edges[v]; !ok {
         edges[v] = make(map[interface{}]int, 0)
      }
      edges[v][u] = w
   }

   var dfs func(x interface{}, vis map[interface{}][]int) []int
   dfs = func(x interface{}, vis map[interface{}][]int) []int {
      _, ok := vis[x]
      if ok {
         return vis[x]
      }

      fn := func(a, b, c, d int, w int) (int, int) {
         first, second := a, b
         if c+w < b {
         } else if c+w < a && c+w > b {
            second = c + w
         } else if c+w > a {
            second = first
            first = c + w
         } else if c+w < a && d+w < b {
            first = c + w
            second = b
         }
         return first, second
      }
      retD := []int{0, 0}
      vis[x] = retD
      for v, w := range edges[x] {
         if _, ok := vis[v]; !ok {
            tmp := dfs(v, vis)
            first, second := fn(vis[x][0], vis[x][1], tmp[0], tmp[1], w)
            vis[x][0] = first
            vis[x][1] = second
         }
      }

      return retD
   }

   vis := make(map[interface{}][]int, 0)
   if len(relations) > 0 {
      u := relations[0][0]
      dfs(u, vis)
   }

   d := 0
   for _, val := range vis {
      if val[0]+val[1] > d {
         d = val[0] + val[1]
      }
   }

   fmt.Println("distance:", d)
   return d
}

测试

1.jpg

2.jpg

func main() {
   maxDistance([][]interface{}{[]interface{}{0, 1, 3}, []interface{}{0, 2, 1}, []interface{}{1, 3, 1}, []interface{}{1, 4, 4}, []interface{}{1, 5, 2}, []interface{}{2, 8, 7}, []interface{}{5, 6, 5}, []interface{}{5, 7, 6}, []interface{}{8, 9, 2}, []interface{}{8, 10, 8}})
   maxDistance([][]interface{}{[]interface{}{"B", "D", 1}, []interface{}{"B", "E", 4}, []interface{}{"B", "F", 2}, []interface{}{"F", "G", 5}, []interface{}{"F", "H", 6}})

   maxDistance1([][]interface{}{[]interface{}{0, 1, 3}, []interface{}{0, 2, 1}, []interface{}{1, 3, 1}, []interface{}{1, 4, 4}, []interface{}{1, 5, 2}, []interface{}{2, 8, 7}, []interface{}{5, 6, 5}, []interface{}{5, 7, 6}, []interface{}{8, 9, 2}, []interface{}{8, 10, 8}})
   maxDistance1([][]interface{}{[]interface{}{"B", "D", 1}, []interface{}{"B", "E", 4}, []interface{}{"B", "F", 2}, []interface{}{"F", "G", 5}, []interface{}{"F", "H", 6}})
}

输出

point: 10 7
distance: 27
point: H E
distance: 12
distance: 27
distance: 12