P4234 最小差值生成树

题目

P4234 最小差值生成树

做法

这题解法差不多,稍微变了一点,还不懂就直接看代码吧

\(update(2019.2):\)还是具体说一下吧,排序,直接加入,到了成环情况下,显然我们要把此边代替掉环内的最小边
就可以用\(LCT\)维护

My complete code

#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<set>
using namespace std;
typedef int LL;
const LL maxn=500000,B=(1<<18),inf=0x3f3f3f3f;
inline LL Read(){
	LL x(0),f(1);char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar();
	return x*f;
}
struct E{
	LL u,v,d;
	inline bool operator <(const E &x)const{
		return d<x.d;
	}
}dis[maxn];
LL Mi=inf,n,m,num,ret,ans;
LL son[maxn][2],fa[maxn],mi[maxn],r[maxn],sta[maxn];
bool visit[maxn];
inline void Update(LL x){
	mi[x]=x;
	if(dis[mi[son[x][0]]].d<dis[mi[x]].d) mi[x]=mi[son[x][0]];
	if(dis[mi[son[x][1]]].d<dis[mi[x]].d) mi[x]=mi[son[x][1]];
}
inline bool Notroot(LL x){
	return son[fa[x]][0]==x||son[fa[x]][1]==x;
}
inline void Pushr(LL x){
	swap(son[x][0],son[x][1]);r[x]^=1;
}
inline void Pushdown(LL x){
	if(r[x]){
		if(son[x][0]) Pushr(son[x][0]);
		if(son[x][1]) Pushr(son[x][1]);
		r[x]=0;
	}
}
inline void Rotate(LL x){
	LL y(fa[x]),z(fa[y]),lz(son[y][1]==x);
	if(Notroot(y)) son[z][son[z][1]==y]=x; fa[x]=z;
	son[y][lz]=son[x][lz^1];
	if(son[y][lz]) fa[son[y][lz]]=y;
	son[x][lz^1]=y, fa[y]=x;
	Update(y),Update(x);
}
inline void Splay(LL x){
	LL y(x),top(0); sta[++top]=y;
	while(Notroot(y)) sta[++top]=y=fa[y];
	while(top) Pushdown(sta[top--]);
	while(Notroot(x)){
		y=fa[x];
		if(Notroot(y)){
			LL z(fa[y]);
			if(((son[z][1]==y)^(son[y][1]==x))==0) Rotate(y);
			else Rotate(x);
		}Rotate(x);
	}
}
inline void Access(LL x){
	for(LL y=0;x;y=x,x=fa[x])
	    Splay(x),son[x][1]=y,Update(x);
}
inline void Makeroot(LL x){
	Access(x),Splay(x),Pushr(x);
}
inline void Split(LL x,LL y){
	Makeroot(x),Access(y),Splay(y);
}
inline LL Findroot(LL x){
	Access(x),Splay(x);
	while(son[x][0]) x=son[x][0];
	return x;
}
inline void Link(LL x){
	LL u(dis[x].u),v(dis[x].v);
	Makeroot(u),Makeroot(v);
	fa[v]=x,fa[x]=u;
}
inline void Delet(LL x){
	LL u(dis[x].u),v(dis[x].v);
	Split(u,v),Splay(x);
	son[x][0]=son[x][1]=fa[son[x][0]]=fa[son[x][1]]=0;
}
int main(){
	n=Read(),m=Read();
	for(LL i=1;i<=m;++i){
		dis[i]=(E){Read(),Read(),Read()};
		dis[i].u|=B,dis[i].v|=B;
	}
	sort(dis+1,dis+1+m);
	dis[0].d=inf;
	for(LL i=1;i<=n;++i)
	    dis[i|B].d=inf;
	LL head(1);
	for(LL i=1;i<=m;++i){
		LL u(dis[i].u),v(dis[i].v);
		if(u==v) continue;
		if(Findroot(u)!=Findroot(v)){
		    Link(i);
			++num,
			visit[i]=true;
		}
		else{
			Makeroot(u),Access(v),Splay(v);
		    visit[mi[v]]=false,
			Delet(mi[v]),
		    visit[i]=true,
			Link(i);
		}
		while(head<=m&&!visit[head]) ++head;
		if(num==n-1&&dis[i].d-dis[head].d<Mi)
			Mi=dis[i].d-dis[head].d;
	}
	printf("%d\n",Mi);
	return 0;
}
posted @ 2019-01-27 23:28  y2823774827y  阅读(359)  评论(0编辑  收藏  举报