BZOJ3669: [Noi2014]魔法森林

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ3669: [Noi2014]魔法森林相关的知识,希望对你有一定的参考价值。

传送门

高级数据结构学傻系列

正解似乎是最短路xjb搞,但是用LCT瞎搞搞也是很吼啊。

从贪心开始,按照每条边a的大小随意sort一下。

对于每个边,我们check两点的联通性,如果联通的话取b最大的值,如果大于当前边的b的话就就删除最大边,把这条边加进去。

如果不连通的话直接添加即可。

LCT滋次这些操作,所以大力LCT即可。

//BZOJ 3669
//by Cydiater
//2017.2.16
#include <iostream>
#include <queue>
#include <map>
#include <cstring>
#include <string>
#include <iomanip>
#include <ctime>
#include <cstdlib>
#include <cstdio>
#include <iomanip>
#include <algorithm>
#include <bitset>
#include <set>
#include <vector>
#include <complex>
using namespace std;
#define ll long long
#define up(i,j,n)	for(int (i)=(j);(i)<=(n);(i)++)
#define down(i,j,n)	for(int (i)=(j);(i)>=(n);(i)--)
#define cmax(a,b)	a=max(a,b)
#define cmin(a,b)	a=min(a,b)
#define FILE		"magicalforest"
const int MAXN=1e6+5;
const int oo=0x3f3f3f3f;
inline int read(){
	char ch=getchar();int x=0,f=1;
	while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();}
	while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
	return x*f;
}
int N,M,len=0,ans=oo;
struct edge{
	int x,y,a,b;
}e[MAXN];
namespace LCT{
	struct SplayTree{
		int son[2],Max,val,fa,tag,id;
		void clear(){son[0]=son[1]=Max=val=fa=0;}
	}t[MAXN];
	inline int isrt(int k){return t[k].fa==0||(t[t[k].fa].son[0]!=k&&t[t[k].fa].son[1]!=k);}
	inline int get(int k){return t[t[k].fa].son[1]==k;}
	inline void rev(int k){
		if(!k)return;
		swap(t[k].son[0],t[k].son[1]);
		t[k].tag^=1;
	}
	inline void reload(int k){
		if(!k)return;
		t[k].Max=t[k].val;t[k].id=k;
		int s1=t[k].son[0],s2=t[k].son[1];
		if(t[s1].Max>t[k].Max){
			t[k].Max=t[s1].Max;
			t[k].id=t[s1].id;
		}
		if(t[s2].Max>t[k].Max){
			t[k].Max=t[s2].Max;
			t[k].id=t[s2].id;
		}
	}
	inline void Pushdown(int k){
		if(!k)return;
		if(t[k].tag){
			rev(t[k].son[0]);rev(t[k].son[1]);
			t[k].tag^=1;
		}
	}
	inline void rotate(int k){
		int old=t[k].fa,oldf=t[old].fa,which=get(k);
		if(!isrt(old))t[oldf].son[t[oldf].son[1]==old]=k;
		t[old].son[which]=t[k].son[which^1];t[t[old].son[which]].fa=old;
		t[k].son[which^1]=old;t[old].fa=k;t[k].fa=oldf;t[0].clear();
		reload(old);reload(k);
	}
	int stack[MAXN],top=0;
	inline void splay(int k){
		top=0;stack[++top]=k;
		for(int tmp=k;!isrt(tmp);tmp=t[tmp].fa){
			stack[++top]=t[tmp].fa;
		}
		while(top)Pushdown(stack[top--]);
		while(!isrt(k)){
			int fa=t[k].fa;
			if(!isrt(fa))rotate(get(fa)==get(k)?fa:k);
			rotate(k);
		}
	}
	inline void access(int k){
		int tmp=0;
		while(k){
			splay(k);t[k].son[1]=tmp;
			reload(k);tmp=k;k=t[k].fa;
		}
	}
	void mrt(int k){
		access(k);splay(k);rev(k);
	}
	int grt(int k){
		access(k);splay(k);
		while(t[k].son[0])k=t[k].son[0];
		return k;
	}
	void Link(int x,int y){
		mrt(x);t[x].fa=y;
	}
	void Cut(int x,int y){
		mrt(x);access(y);splay(y);t[y].son[0]=t[x].fa=0;
		reload(y);
	}
	int col(int x,int y){
		mrt(x);access(y);splay(y);
		return t[y].id;
	}
}
int cnt;
namespace solution{
	inline bool cmp(edge x,edge y){return x.a<y.a;}
	void Prepare(){
		N=read();M=read();
		cnt=N;
		up(i,1,M){
			int x=read(),y=read(),a=read(),b=read();
			e[++len]=(edge){x,y,a,b};
		}
		sort(e+1,e+M+1,cmp);
	}
	void Solve(){
		up(i,1,M){
			cnt++;
			int x=e[i].x,y=e[i].y,a=e[i].a,b=e[i].b;
			if(LCT::grt(x)!=LCT::grt(y)){
				LCT::t[cnt].Max=b;
				LCT::t[cnt].val=b;
				LCT::t[cnt].id=cnt;
				LCT::Link(x,cnt);
				LCT::Link(cnt,y);
			}
			else{
				int id=LCT::col(x,y);
				if(LCT::t[id].val<=b)continue;
				LCT::Cut(e[id-N].x,id);
				LCT::Cut(e[id-N].y,id);
				LCT::t[cnt].Max=b;
				LCT::t[cnt].val=b;
				LCT::t[cnt].id=cnt;
				LCT::Link(x,cnt);
				LCT::Link(cnt,y);
			}
			if(LCT::grt(1)==LCT::grt(N)){
				int id=LCT::col(1,N);
				cmin(ans,a+LCT::t[id].val);
			}
		}
		if(ans==oo)ans=-1;
		cout<<ans<<endl;
	}
}
int main(){
	using namespace solution;
	Prepare();
	Solve();
	return 0;
}

 

以上是关于BZOJ3669: [Noi2014]魔法森林的主要内容,如果未能解决你的问题,请参考以下文章

[BZOJ3669][Noi2014]魔法森林

bzoj3669: [Noi2014]魔法森林

bzoj 3669 [Noi2014]魔法森林

bzoj 3669: [Noi2014]魔法森林

BZOJ3669[Noi2014]魔法森林 LCT

bzoj3669[Noi2014]魔法森林