算法竞赛——进阶指南——acwing 358. 岛屿 基环树求直径

由于每个点都要连一个边。

最终图会分成若干个联通块,每个联通块n个点,n条边。即是一个基环树。

求出每个联通块中任意两点距离最大值(即基环树的直径)求和即可。

一般基环树的问题围绕环来处理。

先把环看出一个点,就能转化为树上问题。

基环树的直径分两类:(把环当成根节点)

1.不在环上,在环的某个节点的子树中。

2.经过环上2点x,y。并延申至x,y所在子树。即dis(x,y)+D[x]+D[y]  .D[x]为dp求直径时维护的,x到其子树中点的最远距离。

我们先求出基环树的环 :s1,s2,s3……s_nm

然后环上每个点做为根节点,执行树形dp,求出与其连接的非环点构成的子树最大直径。并维护出D[x].

这样第一类直径就求出来了。

第二类直径转化为了:

一个环上有nm个点,任意两个点的距离已知,求出最大的f(x,y),f(x,y)=d[x]+d[y]+dist(x,y);

我们可以把环拓展一倍,变成长度为nm*2的区间。

用sm[y]-sm[x]表示dist(x,y),sm[x]即前缀相邻距离和

然后枚举(x,y)区间的右端点,d[y]+sm[y]已知,求左端点x,使得d[x]-sm[x]最大。且y-x<=n (不能经过一个点2次,这样遍历完,x->y顺时针和逆时针的走法都能遍历到)

这里可以用单调队列维护即可。(队列里维护 d[i]-sm[i] 递减,右边的数如果大,那么左边的数肯定就永远选不到了)

 


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值