suxxsfe

一言(ヒトコト)

P4234 最小差值生成树

https://www.luogu.com.cn/problem/P4234

求最小差值生成树

考虑先把边从小到大排序(从大到小也可以,就是反过来而已)
然后一条条边枚举,如果两端点还未联通,直接联通
如果整个图已经联通了,此时可以理解为枚举了边的最大值(因为边权从小到大排序了),最大值确定,就应该要让最小值越大越好,又因为要在这两个端点行成的路径上删掉一个点,那么就删掉环上权值最小的点
所以按照上面的描述每次如果每联通就联通,如果联通了就删路径权值最小边并加新边就行了,用 lct 维护,因为涉及边的信息,还要用新建虚拟节点表示边

然后每次枚举时,如果整个图联通,就用当前边权减去当前全局最小值,全局最小值用带删除的堆维护的,好像有点麻烦了

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<queue>
#include<iomanip>
#include<cstring>
#define reg register
#define EN std::puts("")
#define LL long long
inline int read(){
	register int x=0;register int y=1;
	register char c=std::getchar();
	while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
	while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
	return y?x:-x;
}
#define N 50005
#define M 200005
int n,m;
int U[M],V[M],w[M];
int tmp[10];
struct tr{
	tr *son[2],*fa;
	int tag;
	int valmin,min;
	int valmax,max;
}*null,*pos[N+M],dizhi[N+M];
#define ident(tree,fa) (fa->son[1]==tree)
#define notroot(tree) (tree->fa->son[0]==tree||tree->fa->son[1]==tree)
inline void connect(tr *tree,tr *fa,int k){fa->son[k]=tree;tree->fa=fa;}
inline void pushdown(tr *tree){
	if(!tree->tag) return;
	tree->son[0]->tag^=1;tree->son[1]->tag^=1;
	std::swap(tree->son[0],tree->son[1]);
	tree->tag=0;
}
inline int min(int x,int y){return w[x]<w[y]?x:y;}
inline int max(int x,int y){return w[x]>w[y]?x:y;}
inline void pushup(tr *tree){
	tree->min=min(tree->valmin,min(tree->son[0]->min,tree->son[1]->min));
	tree->max=max(tree->valmax,max(tree->son[0]->max,tree->son[1]->max));
}
inline void rotate(tr *tree){
	tr *fa=tree->fa,*faa=fa->fa;
	pushdown(fa);pushdown(tree);
	int k=ident(tree,fa);
	connect(tree->son[k^1],fa,k);
	tree->fa=faa;
	if(notroot(fa)) faa->son[ident(fa,faa)]=tree;
	connect(fa,tree,k^1);
	pushup(fa);pushup(tree);
}
inline void splay(reg tr *tree){
	reg tr *fa,*faa;
	while(notroot(tree)){
		fa=tree->fa;faa=fa->fa;
		if(notroot(fa)) rotate(ident(tree,fa)^ident(fa,faa)?tree:fa);
		rotate(tree);
	}
}
inline void access(reg tr *x){
	for(reg tr *lastx=null;x!=null;lastx=x,x=x->fa){
		pushdown(x);
		splay(x);
		x->son[1]=lastx;pushup(x);
	}
}
inline void makeroot(tr *x){
	access(x);
	splay(x);
	x->tag^=1;
}
inline tr *findroot(tr *x){
	access(x);splay(x);
	pushdown(x);
	while(x->son[0]!=null) x=x->son[0],pushdown(x);
	splay(x);
	return x;
}
inline int linked(tr *x,tr *y){
	makeroot(x);
	return findroot(y)==x;
}
inline void split(tr *x,tr *y){
	makeroot(x);
	access(y);splay(y);
}
inline void link(tr *x,tr *y){
    makeroot(x);
	if(findroot(y)!=x) x->fa=y;
}
inline void cut(tr *x,tr *y){
    split(x,y);
    x->fa=y->son[0]=null;
}
inline void init(){
	null=&dizhi[0];
	dizhi[0].max=dizhi[0].valmax=m+1;
	for(reg int i=1;i<=n;i++){
		pos[i]=&dizhi[i];
		dizhi[i].son[0]=dizhi[i].son[1]=dizhi[i].fa=null;
		dizhi[i].max=dizhi[i].valmax=m+1;
	}
	w[0]=1e9;w[m+1]=-1e9;
}
inline void creat(int i){
	pos[i]=&dizhi[i];
	dizhi[i].son[0]=dizhi[i].son[1]=dizhi[i].fa=null;
	dizhi[i].min=dizhi[i].valmin=i-n;
	dizhi[i].max=dizhi[i].valmax=i-n;
}
struct edges{
	int u,v,w;
}edge[M];
inline int cmp_edge(edges a,edges b){return a.w<b.w;}
struct HEAP{
	std::priority_queue<int>ins,del;
	inline void delete_(int num){del.push(num);}
	inline void insert(int num){ins.push(num);}
	inline int top(){
		while(!del.empty()&&!ins.empty()&&del.top()==ins.top()) del.pop(),ins.pop();
		return ins.top();
	}
}heap;
int main(){
	n=read();m=read();
	init();
	for(reg int i=1;i<=m;i++) edge[i].u=read(),edge[i].v=read(),edge[i].w=read();
	std::sort(edge+1,edge+1+m,cmp_edge);
	int u,v,ans=1e9;
	for(reg int i=1,cnt=1;i<=m;i++){
		u=U[i]=edge[i].u;v=V[i]=edge[i].v;w[i]=edge[i].w;
		creat(i+n);
		if(u==v) continue;
		if(!linked(pos[u],pos[v])){
			link(pos[u],pos[i+n]),link(pos[v],pos[i+n]);cnt++;
			heap.insert(-w[i]);
		}
		else{
			split(pos[u],pos[v]);
			int tmp=pos[v]->min;
			cut(pos[U[tmp]],pos[tmp+n]);cut(pos[V[tmp]],pos[tmp+n]);
			link(pos[u],pos[i+n]);link(pos[v],pos[i+n]);
			heap.delete_(-w[tmp]);heap.insert(-w[i]);
		}
		if(cnt==n) ans=std::min(ans,w[i]+heap.top());
	}
	printf("%d",ans);
	return 0;
}
posted @ 2020-08-14 14:53  suxxsfe  阅读(148)  评论(0编辑  收藏  举报