[luogu]P3629 [APIO2010]巡逻
2021-06-29 04:03
标签:sed \n set none printf == col 结合 span 给定一棵树,每次要走过每条边。 现在要求加$k$条边,使得走过每条边后走过的距离最小,求这个最小值。 首先不考虑加边,也就是说$k=0$时,是一棵树,显然每条边要经过两次。 考虑加一条边,很容易发现形成的环上的点只需要经过一遍,最终经过的距离就是$((n-1)\times 2-len+2)$,$len$是最大环的长度,明显是树的直径$+1$。 考虑加两条边对答案有什么影响。 分两类考虑: 1.第一次形成的环和第二次没重叠:答案继续减去$len_2+2$. 2.第一次形成的环和第二次有重叠:画过图就很容易发现,重叠部分是经过了两次的,答案就是$((n-1)\times 2-len_1+2_len_2+2+k)$,$k$是这个重叠部分的长度。 那么我们就考虑怎么求出这个重叠部分了。 考虑差分。 第一次已经减去了这个长度,第二次减去这个长度的相反数就相当于加回上了这个长度。 那么我们只需要把直径上的边权置为$-1$,再求一次树的直径即可。 注意第二次的直径可以为$0$(自环)。 我们常用dfs写树的直径,但是我们发现这样子是不能跑负权图的,因为dfs不能统计负权的情况。 而树形dp求树的直径虽然可以跑负权图,但是却很难转移出其他量。 我们结合这两种算法,在第一次时用dfs求出直径,并保存出直径上的边,第二次再跑一次树形dp就可以了。 保存直径上的边的时候,我们需要一点小技巧。 运用费用流中求增广路的方法,我们保存每个节点的祖先节点(从哪里转移过来),并利用成对储存的方法保存每条边和它的反向边。 具体实现见代码。 [luogu]P3629 [APIO2010]巡逻 标签:sed \n set none printf == col 结合 span 原文地址:https://www.cnblogs.com/onglublog/p/10030017.html原题链接:P3629 [APIO2010]巡逻
题意
分析
实现的方式
代码
#include
上一篇:js正则表达式
文章标题:[luogu]P3629 [APIO2010]巡逻
文章链接:http://soscw.com/index.php/essay/99192.html