Full Binary Tree

https://code.google.com/codejam/contest/2984486/dashboard#s=p1&a=1

 

题目可以归纳为以下几点:

1. 给定一棵树,节点从1到N标记,用连接节点的无向边(N - 1条)定义, 比如:

3
2 1
1 3

2. 判断这棵树是否是Full Binary Tree, (除了叶节点,其他的节点必须有两个子节点);

3. 如果不是,需要删除多少个节点(删除节点,以此节点为端点的边也会被删除),可以得到一颗FBT。求最少需要删除几个节点。

 

我自己可以想到的一个比较直观的想法,就是判断现在剩下的节点是否可以组成一颗FBT,如果可以,那么到目前为止删除的就是答案;如果不可以,从这些剩下的节点里再删除一个节点,递归判断,并取最小的结果;经过一点优化,可以解决small practice;这个算法也就是题目分析里面提到的Brute Forcehttps://code.google.com/codejam/contest/2984486/dashboard#s=a&a=1

 

下面是这个算法的实现:

import scala.io.Source

object FullBinaryTree extends App {

  val file = "src/scala/codejam/year2014/round/a/B-small-practice.in"

  val lines = Source.fromFile(file).getLines()

  val T = lines.next().toInt

  def process(t: Int): Unit =
    if (t <= T) {

      val n = lines.next().toInt

      val nodes = (1 to n).foldLeft(Nil: List[Int])((l, x) => x :: l)

      def readEdges(i: Int, edges: List[Edge]): List[Edge] =
        if (i >= n) edges
        else {
          val line = lines.next().split("\\s+").map(_.toInt)
          val x = line(0)
          val y = line(1)
          readEdges(i + 1, Edge(x, y) :: edges)
        }

      val edges = readEdges(1, Nil)

      var cache = Map.empty[String, Int]

      def check(nodes: List[Int], edges: List[Edge], removed: Int): Int = {
        val key = nodes.sorted.mkString("")
        if (cache.contains(key)) {
          cache(key)
        } else {
          val g = new G(nodes, edges)
          val result =
            if (g.isBalance) removed
            else {
              nodes.foldLeft(Integer.MAX_VALUE)((x, n) => {
                val y = check(nodes.filter(_ != n), edges.filterNot(e => e.v == n || e.w == n), removed + 1)
                if (x > y) y
                else x
              })
            }
          cache += (key -> result)
          result
        }
      }

      val removed = check(nodes, edges, 0)

      println(s"Case #$t: $removed")

      process(t + 1)
    }

  process(1)
}

case class Edge(v: Int, w: Int) {
  def other(x: Int) = if (x == v) w else if (x == w) v else throw new Error(s"$x is not a end of this edge")
}

class G(nodes: List[Int], edges: List[Edge]) {
  lazy val degree = nodes.foldLeft(Map.empty[Int, Int])((map, x) => map + (x -> edges.filter(e => e.v == x || e.w == x).size))
  def isBalance =
    if (nodes.size == 1) true
    else {
      val root = degree.filter(x => x._2 == 2)
      edges.size == nodes.size - 1 && root.size == 1 && degree.filter(_ != root.head).forall(x => x._2 == 1 || x._2 == 3)
    }
}

 

那个cache的使用是程序performance的一个关键,否则程序对于某个node list重复计算很多次;

我一开始判断isBalance的方法也要复杂一些,相当于要构建一棵树。看了题目自己的分析后改成了现在这样。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值