已完成今日 Maintaining mst with online edge insertions — no LCT needed 大学习。
在线,只加边,维护最小生成树,小常数 。
还有一个严格证明复杂度的论文,会快一点,但难写一点。
如果按边权升序加入,可以维护按秩合并的并查集, 跳 lca。
尝试在随意加边的过程中维护上述结构。
加入边 时,从 和 开始跳父亲,找到 时刻 和 的根,连起来。此时会破坏本来 继续往上的部分,递归添加 和 原来的父亲。
此时并查集中边权可能不是递增的:在跳父亲的时候折叠起所有边权更小的边。
此时无法按秩合并:按随机权值合并。
此时可能需要替换原 路径的最大边:可以直接删掉。
深度依然是 。
如果边权相同,可以加个 pair 让他们不同。
此时的连通块大小也可以维护。
问号???
为啥对???
code:
mt19937 rnd(time(0));
struct weightdsu{
int fa[maxn],rd[maxn];pii val[maxn];
int siz[maxn];
weightdsu(int n){
for(int i=1;i<=n;i++)fa[i]=i,rd[i]=rnd(),val[i]={inf,inf};
}
int fd(int u,pii w={inf-1,inf}){
while(val[u]<=w){
while(val[fa[u]]<=val[u]){
// siz[fa[u]]-=siz[u];
fa[u]=fa[fa[u]];
}
u=fa[u];
}
return u;
}
void del(int u){
// if(fa[u]==u)return ;
// del(fa[u]);siz[fa[u]]-=siz[u];
}
int ins(int u,pii w={inf-1,inf}){
while(val[u]<=w){
// siz[fa[u]]+=siz[u];
u=fa[u];
}
return u;
}
void merge(int u,int v,pii w){
del(u),del(v);
while(u!=v){
u=ins(u,w),v=ins(v,w);
if(rd[u]<rd[v])swap(u,v);
swap(fa[u],v),swap(val[u],w);
}
ins(u);
}
pii max_path(int u,int v){
int uu=fd(u),vv=fd(v);
if(uu!=vv)return {inf,-1};
if(val[u]>val[v])swap(u,v);
while(fa[u]!=v){
u=fa[u];
if(val[u]>val[v])swap(u,v);
}
return val[u];
}
pii del_path(int u,int v){
int uu=fd(u),vv=fd(v);
if(uu!=vv)return {inf,-1};
if(val[u]>val[v])swap(u,v);
while(fa[u]!=v){
u=fa[u];
if(val[u]>val[v])swap(u,v);
}
v=u;
while(fa[v]!=v){
// siz[fa[v]]-=siz[v];
v=fa[v];
}
fa[u]=u;
pii res={inf,inf};swap(res,val[u]);
return res;
}
pii add_edge(int u,int v,pii w){
pii res=del_path(u,v);
if(res<=w)swap(res,w);
merge(u,v,w);
return res;
}
};