校园网改造(AHOI2003)

本文深入探讨了使用O(n)复杂度解决树网问题的方法,通过定义关键变量并巧妙利用树的性质,实现了从O(n^2)到O(n)的优化。文中详细解释了算法的核心思路及数学推导过程,旨在帮助读者理解如何高效地解决此类问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这道题代码实在是太长了,而标程又是错的,写起来一定会耗不少时间,因此这里就不写代码了,就说下思路吧。
 
第一次看到这题,想到了NOIP2007树网的核那道题,只是那道题与这道题相比实在是小巫见大巫了……首先枚举的不是最长路,点的范围是0~10000不允许枚举,其它的地方与07年那道题基本无异,我甚至怀疑07年那道题是不是这道题的简化版?
 
不瞎扯了,先说一下O(n2)的思路:
很简单,就是枚举起点和终点,然后各个不属于路径上的点都要找一个到路径上的点的距离的最小值,把最小值进行累加即可得出结果。
 
下面重点将O(n)的思路:
O(n)的思路就是很好的用到了树的相关知识,因为题中给出了网关这个概念,所以应该很好想到用树。
首先定义三种变量:
  i.downsum 表示以i为根的子结点到i点的距离
  i.allsum 表示所有点到i的距离
  i.ge 表示以i为根的子结点的个数
再定义:
  f[i] 表示以i为起点的向下的一条路径的权值和
如果i选择了它的子结点j与k的话,那么新的延迟总和:
  {f[j]-(j.allsum-j.downsum)}+{f[k]-(k.allsum-k.downsum)}+{i.allsum-(j.downsum+j.ge*w(i,j)-(k.downsum+k.ge*w(i,k))}
这里详细解释一下:
  第一个{}里表示以结点j为根的子树上的所有结点到新路径的距离总和
  第二个{}里表示以结点k为根的子树上的所有结点到新路径的距离总和
  第三个{}里表示其余结点(既不属于j的子结点也不属于k的子结点)的所有结点到新路径的距离总和
上面的式子经过化简之后可以得到:
  延迟总和=i.allsum-{[j.downsum+j.ge*w(i,j)]-[k.downsum+k.ge*w(i,k)]-[f[j]-(j.allsum-j.downsum)]-[f[k]-(k.allsum-k.downsum)]}
显然i的取值至于j和k的取值有关,因此我们只需找一个最大的j和k来满足i的值最小。
再看看我们定义的那三种变量,其中i.downsum和i.ge因为只与子结点有关,因此通过递归可以得出结果,但是i.allsum就不行,但是我们可以换种思路,用自上向下的方法求出i.allsum。
有一些式子是显然成立的:
  root.allsum=root.downsum
  i.allsum=father[i].allsum-i.ge*w(father[i],i)+(n-i.ge)*w(father[i],i)
 
总而言之,认真的思考与大胆的猜想才是解决DP题目的关键。同时对于明显的给出树的问题,例如有明显的子结点与父结点之间的联系的,一定要想到树,这样的话父结点与子结点是很容易建立关系的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值