LCT维护MST

以MST的模板为例:

题目链接:MST模板


LCT维护MST一般是,图存在加边的动态MST,如果是删边,那么我们可以考虑使用时间倒流实现把删边变加边。但是如果是即加边又删边就不行了。

对于加边时,如果此两点没有连通,肯定是直接连接。但是如果连接了呢?,,我们就需要用当前的边来替换路径的最大值。然后我们还需要维护当前路径最大边的编号,方便cut断边。

LCT维护的点权,但是我们需要边权,所以我们可以用点来表示边。


AC代码:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=3e5+10;
int n,m,idx,w[N],res;
int cnt,st[N];
struct node{int ch[2],fa,mx,id,re;}t[N];
inline void push_up(int p){
	t[p].id=p,t[p].mx=w[p];
	if(t[t[p].ch[0]].mx>t[p].mx) t[p].id=t[t[p].ch[0]].id,t[p].mx=t[t[p].ch[0]].mx;
	if(t[t[p].ch[1]].mx>t[p].mx) t[p].id=t[t[p].ch[1]].id,t[p].mx=t[t[p].ch[1]].mx;
}
inline void push_re(int p){swap(t[p].ch[0],t[p].ch[1]); t[p].re^=1;}
inline void push_down(int p){
	if(t[p].re){
		if(t[p].ch[0])	push_re(t[p].ch[0]);
		if(t[p].ch[1])	push_re(t[p].ch[1]); t[p].re^=1;
	}
}
inline bool isroot(int x){return t[t[x].fa].ch[0]!=x&&t[t[x].fa].ch[1]!=x;}
inline void rotate(int x){
	int y=t[x].fa,z=t[y].fa,k=t[y].ch[1]==x,w=t[x].ch[!k];
	if(!isroot(y))	t[z].ch[t[z].ch[1]==y]=x; t[x].ch[!k]=y; t[y].ch[k]=w;
	if(w)	t[w].fa=y; t[y].fa=x; t[x].fa=z;	push_up(y);
}
inline void splay(int x){
	cnt=1;	st[cnt]=x; int y=x;
	while(!isroot(y))	st[++cnt]=y=t[y].fa;
	while(cnt)	push_down(st[cnt--]);
	while(!isroot(x)){
		int y=t[x].fa,z=t[y].fa;
		if(!isroot(y))	rotate((t[y].ch[0]==x)^(t[z].ch[0]==y)?x:y); rotate(x);
	}push_up(x);
}
inline void access(int x){
	for(int y=0;x;x=t[y=x].fa) splay(x),t[x].ch[1]=y,push_up(x); 
}
inline void makeroot(int x){
	access(x); splay(x); push_re(x);
}
inline int find(int x){
	access(x); splay(x); while(t[x].ch[0]) push_down(x),x=t[x].ch[0]; 
	splay(x);	return x;
}
inline void split(int x,int y){
	makeroot(x); access(y); splay(y);
}
inline void link(int x,int y){
	makeroot(x); 	if(find(y)!=x)	t[x].fa=y;
}
inline void cut(int x,int y){
	makeroot(x); 
	if(find(y)==x&&t[y].fa==x&&!t[y].ch[0]) t[y].fa=t[x].ch[1]=0,push_up(x);
}
signed main(){
	cin>>n>>m;	idx=n;
	for(int i=1,a,b,c;i<=m;i++){
		scanf("%d %d %d",&a,&b,&c);
		w[++idx]=c;	makeroot(a);
		if(find(b)!=a){
			link(a,idx);	link(idx,b);	res+=c;	continue;
		}
		split(a,b);	int now=t[b].id;
		if(t[now].mx<=c)	continue;
		res+=(c-t[now].mx),splay(now);
		t[t[now].ch[0]].fa=t[t[now].ch[1]].fa=0;
		link(a,idx),link(idx,b); 
	}
	cout<<res<<endl;
	return 0;
}
全部评论

相关推荐

敢逐云霄志:你打招呼语怎么能这么长,hr都没看下去的欲望,简明扼要说重点,就读于某某学校某某专业,26届应届毕业生,学信网可查,先后在某某公司实习过(如有),然后做过什么项目,想找一份什么样的工作,可实习几个月以上,期待您的回复。
点赞 评论 收藏
分享
||&nbsp;先说下主播个人情况:211本,暑期实习之前有过一段中大厂的后端实习,暑期拿过腾讯的实习offer,综合考虑业务和语言最终去了美团。实习期间体感还是不错的,5月初去的,去了就一直急着要需求做,担心因为没有产出导致转正失败,在第二个星期就和mt透露我希望能够留用。虽然第一个由于美团新人landing的友好性基本没做什么需求,但是后面也写出了小2w行的代码量(不包含单测)。中期经常主动加班赶需求,经常持续一两个星期加班到10点甚至更后面。mt对我确实不错,也是言传身教,实习期间给我讲了很多关于单测,ddd,set化等的理解,也是受益匪浅,此外在做需求的时候,也能看出把比较有含金量的部分交给我做...
菜菜菜小白菜菜菜:我在字节实习了四个月,有转正的压力所以周末大部分也在公司自学,也是因为一些原因转正拖的很久,这个点还没答辩,过段时间才回去答辩。整个不确定性的焦虑贯穿了我的秋招三个月,我也曾经犹豫过是不是应该放弃转正走秋招更快,最后因为沉没成本一直舍不得放弃,前前后后七个月真的挺累的,尤其是没有来字节实习的同学已经校招拿到意向时更加焦虑。这段时间也跟mentor聊了很多次,他告诉我未来工作上或者生活上,比这些更头疼的事情会更多,关键还是要调整好自己的心态。转正没有通过从过程上来看其实跟你自身没太大的关系,拖了三个月不出结果显然是ld的问题,并且今年美团最近的开奖大家似乎都不是很乐观,所以不去也罢。我在字节实习的时候,6月份有一个赶上春招末期的25届同事刚面进来,也拿到了小sp的薪水。不要对这件事有太大的压力,时代的问题罢了
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务