最小差值生成树

XVIII.最小差值生成树

这题\(m^2\)暴力求最小生成树应该是过不去的……估计只有LCT能过去了。

然后就是同IV.[NOI2014]魔法森林一致的方法,排序之后暴力断边连边即可。

注意会有自环!!!虽然我也不知道为什么没判自环算我MLE……

代码:

#include<bits/stdc++.h>
using namespace std;
int n,m,res=0x3f3f3f3f;
struct EDGE{
	int u,v,w;
	friend bool operator <(const EDGE &x,const EDGE &y){
		return x.w<y.w;
	}
}e[200100];
multiset<int>s;
#define lson t[x].ch[0]
#define rson t[x].ch[1]
struct LCT{
	int fa,ch[2],mn,val;
	bool rev;
}t[300100];
inline int identify(int x){
	if(x==t[t[x].fa].ch[0])return 0;
	if(x==t[t[x].fa].ch[1])return 1;
	return -1;
}
inline void pushup(int x){
	t[x].mn=x;
	if(lson&&t[t[x].mn].val>t[t[lson].mn].val)t[x].mn=t[lson].mn;
	if(rson&&t[t[x].mn].val>t[t[rson].mn].val)t[x].mn=t[rson].mn;
}
inline void REV(int x){t[x].rev^=1,swap(lson,rson);}
inline void pushdown(int x){
	if(!t[x].rev)return;
	if(lson)REV(lson);
	if(rson)REV(rson);
	t[x].rev=0;
}
inline void rotate(int x){
	register int y=t[x].fa,z=t[y].fa,dirx=identify(x),diry=identify(y),b=t[x].ch[!dirx];
	if(diry!=-1)t[z].ch[diry]=x;t[x].fa=z;
	if(b)t[b].fa=y;t[y].ch[dirx]=b;
	t[y].fa=x,t[x].ch[!dirx]=y;
	pushup(y),pushup(x);
}
inline void pushall(int x){if(identify(x)!=-1)pushall(t[x].fa);pushdown(x);}
inline void splay(int x){for(pushall(x);identify(x)!=-1;rotate(x))if(identify(t[x].fa)!=-1)rotate(identify(x)==identify(t[x].fa)?t[x].fa:x);}
inline void access(int x){for(register int y=0;x;x=t[y=x].fa)splay(x),rson=y,pushup(x);}
inline void makeroot(int x){access(x),splay(x),REV(x);}
inline int findroot(int x){access(x),splay(x),pushdown(x);while(lson)x=lson,pushdown(x);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),t[x].fa=y;}
inline void cut(int x,int y){split(x,y),t[y].ch[0]=t[x].fa=0,pushup(y);}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)t[i].val=0x3f3f3f3f;
	for(int i=1;i<=m;i++)scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
	sort(e+1,e+m+1);
	for(int i=1;i<=m;i++){
		t[i+n].val=e[i].w;
		if(findroot(e[i].u)!=findroot(e[i].v))s.insert(e[i].w),link(e[i].u,i+n),link(e[i].v,i+n);
		else{
			if(e[i].u==e[i].v)continue;
			split(e[i].u,e[i].v);
			int tmp=t[e[i].v].mn;
			cut(e[tmp-n].u,tmp),cut(e[tmp-n].v,tmp),s.erase(s.find(t[tmp].val)),s.insert(e[i].w),link(e[i].u,i+n),link(e[i].v,i+n);
		}
		if(s.size()==n-1)res=min(res,e[i].w-*s.begin());
	}
	printf("%d\n",res);
	return 0;
}

原文地址:https://www.cnblogs.com/Troverld/p/14602119.html