萌新求助
查看原帖
萌新求助
72468
「 」楼主2021/1/9 10:49

这道题机房人均会做,就我不会,感觉思路没有问题。

大概是你维护 maxamaxamaxbmaxb 两个指针,可以证明如果在保证 11nn 联通的情况下,两个必然是存在一个单调增另一个单调减的关系,然后用 mapmap 来存边一下,移动两个指针并加入相应的边,然后用 LCTLCT 维护一下对应的连通性就可以了?

#include<bits/stdc++.h>
using namespace std;
#define It map<int,int>::iterator
const int N=5e4+5,M=1e5+5;
const int A=5e4+5,B=5e4+5;
int n,m,id[M],tot;
struct Edge{int u,v,a,b;}e[M];
map<int,map<int,int> > mpa,mpb;
struct Data{int data,pos;};
bool operator < (const Data a,const Data b){return a.data<b.data;}
bool operator > (const Data a,const Data b){return a.data>b.data;}
struct Link_Cut_Tree{
	struct Node{int fa,tag,son[2];Data data,maxn;}tr[N+M];
	int get_son(int u){return tr[tr[u].fa].son[1]==u;}
	bool is_root(int u){return tr[tr[u].fa].son[0]!=u&&tr[tr[u].fa].son[1]!=u;}
	void up(int u){tr[u].maxn=max(tr[u].data,max(tr[tr[u].son[0]].maxn,tr[tr[u].son[1]].maxn));}
	void update(int u,int tag){if(tag)swap(tr[u].son[0],tr[u].son[1]),tr[u].tag^=1;}
	void down(int u){
		update(tr[u].son[0],tr[u].tag);
		update(tr[u].son[1],tr[u].tag);
		tr[u].tag=0;
	}
	void clear_tag(int u){if(!is_root(u))clear_tag(tr[u].fa);down(u);}
	void Rotate(int u){
		int fa=tr[u].fa,gfa=tr[fa].fa,k=get_son(u);
		if(!is_root(fa)) tr[gfa].son[get_son(fa)]=u;
		tr[fa].son[k]=tr[u].son[!k],tr[tr[u].son[!k]].fa=fa;
		tr[u].son[!k]=fa,tr[fa].fa=u,tr[u].fa=gfa;
		up(fa),up(u);
	}
	void Splay(int u){
		clear_tag(u);
		for(int fa=tr[u].fa;!is_root(u);Rotate(u),fa=tr[u].fa)
		if(!is_root(fa)) Rotate(get_son(u)==get_son(fa)?fa:u);
	}
	void Access(int u){
		int fuck=u;
		for(int v=0;u;v=u,u=tr[u].fa)
		Splay(u),tr[u].son[1]=v,up(u);
		Splay(fuck);
	}
	void Make_Root(int u){Access(u),update(u,1);}
	bool Judge(int u,int v){Make_Root(u),Make_Root(v);return tr[u].fa;}
	bool Link(int u,int v){
		if(Judge(u,v)) return false;
		Make_Root(u),tr[u].fa=v;
		return true;
	}
	bool Cut(int u,int v){
		Make_Root(u),Access(v);
		if(tr[v].son[0]!=u) return false;
		tr[v].son[0]=tr[u].fa=0,up(v);
		return true;
	}
	int Split(int u,int v){Make_Root(u),Access(v);return v;}
}t;
int main(){
	cin>>n>>m,tot=n;
	for(int i=1;i<=m;++i){
		id[i]=++tot;
		scanf("%d%d%d%d",&e[i].u,&e[i].v,&e[i].a,&e[i].b);
		t.tr[tot].data.data=e[i].a,t.tr[tot].data.pos=i;
		mpa[e[i].a][e[i].b]=i,mpb[e[i].b][e[i].a]=i;
	}
	int maxa=A-1,maxb=0,res=1e9+7;
	while(maxa){
		while(maxb+1<B&&!t.Judge(1,n)){
			++maxb;
			for(It i=mpb[maxb].begin();i!=mpb[maxb].end()&&i->first<=maxa;++i){
				if(t.Judge(e[i->second].u,e[i->second].v)){
					int tmp=t.tr[t.Split(e[i->second].u,e[i->second].v)].maxn.pos;
					if(e[tmp].a<=e[i->second].a) continue;
					t.Cut(e[tmp].u,id[tmp]),t.Cut(e[tmp].v,id[tmp]);
				}
				t.Link(e[i->second].u,id[i->second]),t.Link(e[i->second].v,id[i->second]);
			}
		}
		// printf("----%d %d\n",maxa,maxb);
		if(t.Judge(1,n)) res=min(res,maxa+maxb);
		for(It i=mpa[maxa].begin();i!=mpa[maxa].end()&&i->first<=maxb;++i)
		t.Cut(e[i->second].u,id[i->second]),t.Cut(e[i->second].v,id[i->second]);
		maxa--;
	}
	if(res>=1e9+7) printf("-1\n");
	else printf("%d\n",res);
	return 0;
}
2021/1/9 10:49
加载中...