动态mst
动态mst是在可以加边的图中动态地维护这个图的最小生成树,例如下面的问题
给定一个图,每次会加入一条边,每次加入边后输出最小生成树的值
(或给出两个点x,y,输出最小化的联通两点需要边的最大值)
回忆 kruskalkruskalkruskal 求最小生成树的过程,我们是将所有边按边权排序后,再一个个将边插入,维护当前的最小生成树,设当前插入的边连接 x,yx,yx,y 两点
- 若 x,yx,yx,y 未联通,直接加入
- 若 x,yx,yx,y 已联通,插入这条边后必然会形成一个环,且这条边一定是这个环中值最大的边,删去这个边更优,所以不加入
而动态维护最小生成树的操作原理也类似,假设当前插入边连接 x,yx,yx,y 两点,边权为 www
- 若 x,yx,yx,y 未联通,直接加入
- 若 x,yx,yx,y 已联通,插入这条边后必然会形成一个环,我们应该删掉这个环中权值最大的一条边
具体地说,我们在一直维护一颗树,每次进来一个边连接 x,yx,yx,y ,权值为 www
先看 x,yx,yx,y 是否联通,如果未联通,就将这条边加入维护的树;
如果已联通,先找到 x,yx,yx,y 路径上权最大的边 emaxe_{max}emax ,值为 wmaxw_{max}wmax :
- 若 wmax≤ww_{max}\leq wwmax≤w , 则新进来的边值是环中最大的,不插入
- 若 wmax>ww_{max}> wwmax>w , 则先删除 emaxe_{max}emax ,再将新进来的边加入
不难发现,只要保证先删边再加边就能保证我们一直在维护一个树(或者森林),我们需要在这颗树上删边和加边,还需要找到一条链上最大的边权 ,这样就可以想到用 link_cut treelink\_cut\:treelink_cuttree 来维护这颗树
这里不会 lctlctlct 的同学也可以继续看下去,当然先去看看 lctlctlct 也没问题,这里稍微提一下:
lctlctlct 是用 splaysplaysplay 来维护每个树链,access(x)access(x)access(x) 操作可以将 xxx 到根的链弄到一个 splaysplaysplay 里,make_root(x)make\_root(x)make_root(x) 操作可以将 xx