图论题,题目重新叙述为:

一棵树从根出发遍历完所有节点的最短总路径之和

令 \(p(x)\) 表示节点 \(x\) 到根的路径长,\(sum\) 表示所求总路径之和,则:

\(sum_{min}=2 \times \sum_i ductLength_i - max\{p(x)\}\)

证明

最优解与深度优先遍历有关,先证明如下问题:

若最终遍历还要回到根节点,则最短路径之和 \(sum2_{min}\) 就是深度优先遍历的路径之和 \(deepsum\)

利用归纳法可以证明深度优先遍历路径和 \(deepsum=2 \times \sum_i ductLength_i\)

若最终遍历回到根节点,则任何一条边必然至少被遍历两次,因此 \(sum2_{min} \geq 2 \times \sum_i ductLength_i\),所以:

\(sum2_{min}=deepsum=2 \times \sum_i ductLength_i\)

将回到根节点的遍历法分为两步:

1. 遍历到最后一个节点 \(x\)

2. 回到根节点

因此:

\(\ sum2=sum+p(x)\)

\(\begin{equation}\begin{split}sum_{min}&=sum2_{min}-max\{p(x)\} \\ &=2 \times \sum_i ductLength_i - max\{p(x)\}\end{split}\end{equation}\)

可以证明深度优先遍历时使得 \(sum2\) 取最小值和 \(p(x)\) 取最大值并不冲突,综上,命题得证

 1 class Graph:
 2     def __init__(self, n):
 3         self.n = n                       # 节点个数
 4         self.g = [[] for i in range(n)]  # 邻接表表示的图模型
 5
 6     def count(self):
 7         return self.n
 8
 9
10     # 新增一条边
11     def append(self, i, j, l=None):
12         self.g[i].append((j, l))
13
14
15     # 返回从x的后继边的集合
16     def nexts(self, x):
17         return self.g[x]
18
19 # DFS算法
20 class DeepFirstSearch:
21     def __init__(self, begin, g):
22         self.begin = begin         # 开始节点
23         self.searchHandle = None   # 搜到新节点时触发
24         self.g = g                 # 搜索图
25
26     def _onSearch(self, prev, nextNode, l):
27         if self.searchHandle != None:
28             self.searchHandle(prev, nextNode, l)
29
30     def do(self):
31         a = [self.begin]
32         marks = [False] * self.g.count()
33         marks[self.begin] = True
34         while len(a) > 0:
35             x = a.pop()
36             for yl in self.g.nexts(x):
37                 y = yl[0]
38                 l = yl[1]
39                 if not marks[y]:
40                     self._onSearch(x, y, l)
41                     marks[y] = True
42                     a.append(y)
43
44
45 class PowerOutage:
46     def search(self, x, y, l):
47         self.deeps[y] = self.deeps[x] + l
48         self.maxDeep = max(self.maxDeep, self.deeps[y])
49
50     def estimateTimeOut(self, f, t, l):
51         maxNodeCount = 50
52         g = Graph(maxNodeCount)
53         for i in range(len(f)):
54             g.append(f[i], t[i], l[i])
55
56         self.deeps = [0] * maxNodeCount
57         self.maxDeep = 0
58         dfs = DeepFirstSearch(0, g)
59         dfs.searchHandle = self.search
60         dfs.do()
61
62         result = 2 * sum(l) - self.maxDeep
63         return result
64
65
66 # test
67 o = PowerOutage()
68
69 # test case
70 assert(o.estimateTimeOut((0,), (1,), (10,)) == 10)
71 assert(o.estimateTimeOut((0,1,0), (1,2,3), (10,10,10)) == 40)
72 assert(o.estimateTimeOut((0,0,0,1,4), (1,3,4,2,5), (10,10,100,10,5)) == 165)
73 assert(o.estimateTimeOut((0,0,0,1,4,4,6,7,7,7,20), (1,3,4,2,5,6,7,20,9,10,31), (10,10,100,10,5,1,1,100,1,1,5)) == 281)
74 assert(o.estimateTimeOut((0,0,0,0,0), (1,2,3,4,5), (100,200,300,400,500)) == 2500)

View Code

转载于:https://www.cnblogs.com/valaxy/p/3440806.html

SRM144 DIV2 1100相关推荐

  1. 微信小程序picker 轮滑1-100的实现

    实现的效果 一般普通的使用是在data初始化数据的时候给一个数组例如 array: ['中国', '美国', '英国', '日本'], 那么弹出的数据也就是这么几个 如果是1-100  很显然不能用这 ...

  2. (C++)寻找1-100以内所有素数,复杂度为O(nsqrt(n))与O(nloglogn)的两种方法

    注意:1既不是质数也不是合数,2是质数. 1. 复杂度为O(nsqrt(n)) 原理:先写一个判断整数是否为素数的函数,其复杂度为sqrt(n),其原理是对于一个数n,如果它有除了1和自身之外的因子, ...

  3. #423 Div2 D

    #423 Div2 D 题意 构造一个 n 个节点的树,恰好有 k 个叶子节点 (叶子节点的定义是只与树上的某一个节点存在连边),要求任意两个叶子节点的距离的最大值最小,距离为两个节点间边的数量,输出 ...

  4. Codeforces Round #694 (Div. 1 + Div2)(A ~ H,8题全,超高质量题解)【每日亿题】2021/2/1、2/2

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 目录 [每日亿题]Codeforces Round #694 (Div. 1 + Div2)(A ~ ...

  5. Linux环境下编写一个shell程序,此程序的功能:随机生成一个1-100的数(答案)让用户猜

    题目:编写一个shell程序,此程序的功能:随机生成一个1-100的数(答案)让用户猜,如果用户猜的数大于答案,则提示大了,如果用户猜的数小于答案,则提示小了.当用户猜对时提示:猜对了. #! /bi ...

  6. 【C/C++学院】0831-类与对象的异常/面试100题1-100

    类与对象的异常 Cpp异常 #include <iostream> #include <string.h>using namespace std;//标识错误的类型 class ...

  7. 标题1100: 简略计算器

    2019独角兽企业重金招聘Python工程师标准>>> 标题描写 读入一个只包含 , -, *, / 的非负整数核算表达式,核算该表达式的值. 输入 检验输入包含若干检验用例,每个检 ...

  8. excel随机数_Excel使用函数生成1100的不重复随机数 2种方法

    有时候我们需要得到某个区间的不重复随机数,比如我们想获得1-100的不重复随机数 方法如下 1.数组公式直接生成 比较炫技的解法,在A1单元格输入以下公式,然后按下ctrl+shift+enter , ...

  9. 求1-100之间的所有素数

    在控制台输出1-100之间的所有素数.素数是指一个正整数只能被1和其本身整除. 1 public class PrimeNumber { 2 public static void main(Strin ...

最新文章

  1. 16 分频 32 分频是啥意思_Verilog中任意分频的实现
  2. 使用深度学习和OpenCV的早期火灾检测系统
  3. css图片悬停边框,CSS悬停边框使内联元素稍微调整
  4. mysql数据库死锁 情景一
  5. python实现高校教务管理系统_python+mysql实现教务管理系统
  6. Java怎么测并发量_如何测试一个web网站的性能(并发数)?
  7. 对话腾讯云汽车业务副总经理李博:构建出行大版图,腾讯云迈向新征程
  8. C++ VS C# 结构体和对象的细微区别
  9. java编写github监控_【原创工具】github监控工具
  10. Emacs-小白入坑之旅
  11. mysql5.7用户管理
  12. 想捧金饭碗? 修炼这25项技能就够了!
  13. MyGameDemo:打砖块
  14. 时序图与状态图(Rose) - Windows XP经典软件系列
  15. Unity3D之UGUI基础2:Text文本
  16. RFC 5961翻译
  17. java的inputbox,Excel|VBA的inputbox函数和inputbox方法
  18. 为什么腾讯微云显示服务器繁忙,谁知道腾讯微云是干什么?
  19. 如何将vob格式转换成mp4
  20. PAT(甲级)渡劫(一)-Public Bike Management

热门文章

  1. vue-typescript-toast (一款适用于pc平台的简单toast)
  2. python3 识别图片文字
  3. 小型自动化运维--expect脚本之自动同步
  4. subversion commit 报错A checksum mismatch occurred
  5. 很牛逼的短链接,我们一起来晒晒短链接程序(转)
  6. RHEL5.5 安装 oracle 11g
  7. 跨系统远程登录用Linux系统远程登录windows7
  8. TOML-to-Go : 帮你快速生成 Go 结构体
  9. 微信企业号:shell定时发送图片 到 指定人
  10. 【NetApp】FC盘不能和装有ATA盘的DS14盘柜接入同一个loop中。