这道题机房人均会做,就我不会,感觉思路没有问题。
大概是你维护 maxa 和 maxb 两个指针,可以证明如果在保证 1 和 n 联通的情况下,两个必然是存在一个单调增另一个单调减的关系,然后用 map 来存边一下,移动两个指针并加入相应的边,然后用 LCT 维护一下对应的连通性就可以了?
#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;
}