codechef MXMN

博客介绍了如何解决MXMN问题,即求两点间所有简单路径最大权值的最小值的乘积之和。通过构建Kruskal重构树并结合点分树,对每一对点在重构树中的LCA进行处理,同时维护另一个图中的相关答案。文中提到,点分树的合并过程类似线段树,并特别指出在处理同一点在不同子树中的情况时,需要考虑边的上下关系以正确计算答案。最后,提出了通过赋权差分简化问题的方法,将时间复杂度优化至O(nlogn)。
摘要由CSDN通过智能技术生成

题意:
定义一条路径的权值为经过边边权的最大值
两点u,v的权值为f(u,v)等于uv之间所有简单路径的权值的最小值
两张图G1,G2,都有n个点G1点编号为 [ 1 , n ] [1,n] [1,n],G2编号为 [ n + 1 , n + n ] [n+1,n+n] [n+1,n+n]
∑ u , v ∈ [ 1 , n ] f ( u , v ) ∗ f ( u + n , v + n ) \sum_{u,v\in [1,n]} f(u,v)*f(u+n,v+n) u,v[1,n]f(u,v)f(u+n,v+n)


显然f(u,v)为最小生成树的路径最大值
考虑在uv之间的最大权边上统计uv的答案
可以用边分治,但我不怎么会打,有点麻烦
由于是最小生成树,考虑使用kruskal重构树,对两个图都建kruskal重构树
那么u,v的答案就会在lca处统计到
在第一个重构树中枚举lca,那么这个地方的权值只对左右两子树之间的答案有贡献,现在需要求左右两子树在另一个图中的答案,我们需要一种类似左右子树合并的做法来统计。
为了保持复杂度,我们需要使用一种较浅的结构来支持合并,这就想到了点分树,对另一个kruskal重构树建点分树,那么一开始,每一个点只存有在点分树中到根的路径,接着对于枚举的lca,将左右两点分树合并,顺便维护答案,点分树合并和线段树合并类似,如果对于两边子树有同一个点,那么这个点要往下走,合并下面的子树,否则只用保留其一。
那么现在的问题在于,点分树的两个子图的同一点,如何计算答案
1
重心父亲和重心儿子可能没有祖孙后代关系
如图,两条黑边走下去的重心,两块之间的答案就是方点,答案就是个数之积乘上该重心的权值,但是对于黑边和蓝边的答案是lca就是绿点,所以在储存点分树的时候要记下那条边是往上的,那么这条边的要记录下那一块点与方点的lca权值和,蓝边与黑边的答案就是该和乘上其他两个的大小。
时间复杂度 O ( n log ⁡ n ) O(n \log n) O(nlogn)

事实上可以对kruskal的边赋权为点权的差分,将max变为权值和,再做点分树合并,更简单点。

#include<cstring>
#include<cstdio>
#include<algorithm>
#define N 200100
#define M 3800000
#define mo 998244353
using namespace std;
int s[N][3],son[N][2],n,m,top,ps[N+N],c,v[N],sz[M],sn[M][3],sm[M],Fa[N],siz[N],rt,hd,tl,que[N],fa[N],R[N],tot,ans,f[19][N+N],deep[N]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值