点击这里查看原题
将所有路径按a升序排序,用LCT维护路径上最大的b,将边权化为点权,如果加入一条边x,其两端点分别为u,v,那么将u与i+x连边,v与i+x连边。
如果(u,v)路径最大的b值大于当前边的b,那么删去b最大的边。
注意:access操作中必须pushup,因为这个调了好久
/*
User:Small
Language:C++
Problem No.:3
*/
#include<bits/stdc++.h>
#define ll long long
#define inf 99999999
using namespace std;
const int M=200005;
int n,m,pre[M],fa[M],ch[M][2],val[M],mx[M],stk[M],ans=inf;
bool rev[M];
struct edge{
int u,v,a,b;
bool operator<(const edge &y)const{
return a<y.a;
}
}e[M];
bool isroot(int x){
return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;
}
bool get(int x){
return ch[fa[x]][1]==x;
}
void pushup(int rt){
int &l=ch[rt][0],&r=ch[rt][1];
mx[rt]=rt;
if(val[mx[l]]>val[mx[rt]]) mx[rt]=mx[l];
if(val[mx[r]]>val[mx[rt]]) mx[rt]=mx[r];
}
void pushdown(int rt){
int &l=ch[rt][0],&r=ch[rt][1];
if(rev[rt]){
rev[rt]^=1;
rev[l]^=1;
rev[r]^=1;
swap(l,r);
}
}
void rotate(int x){
int y=fa[x],z=fa[y],side=get(x);
if(!isroot(y)) ch[z][ch[z][1]==y]=x;
fa[x]=z;
ch[y][side]=ch[x][side^1];
fa[ch[y][side]]=y;
ch[x][side^1]=y;
fa[y]=x;
pushup(y);
pushup(x);
}
void splay(int x){
int tp=0;
stk[++tp]=x;
for(int u=x;!isroot(u);u=fa[u]) stk[++tp]=fa[u];
while(tp) pushdown(stk[tp--]);
while(!isroot(x)){
int y=fa[x];
if(!isroot(y)) rotate(get(x)==get(y)?y:x);
rotate(x);
}
}
void access(int x){
int t=0;
for(int t=0;x;t=x,x=fa[x]){
splay(x);
ch[x][1]=t;
pushup(x);
}
}
void makeroot(int x){
access(x);
splay(x);
rev[x]^=1;
}
void link(int x,int y){
makeroot(x);
fa[x]=y;
splay(x);
}
void cut(int x,int y){
makeroot(x);
access(y);
splay(y);
fa[x]=ch[y][0]=0;
}
int query(int x,int y){
makeroot(x);
access(y);
splay(y);
return mx[y];
}
int find(int x){
return x==pre[x]?x:pre[x]=find(pre[x]);
}
int main(){
freopen("data.in","r",stdin);//
ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=1;i<=n;i++) pre[i]=i;
for(int i=1;i<=m;i++) cin>>e[i].u>>e[i].v>>e[i].a>>e[i].b;
sort(e+1,e+m+1);
for(int i=1;i<=m;i++){
int u=e[i].u,v=e[i].v;
if(find(u)==find(v)){
int t=query(u,v);
if(val[t]<=e[i].b) continue;
cut(t,e[t-n].u);
cut(t,e[t-n].v);
}
else pre[find(u)]=find(v);
val[i+n]=e[i].b;
mx[i+n]=i+n;
link(u,i+n);
link(v,i+n);
if(find(1)==find(n)) ans=min(ans,e[i].a+val[query(1,n)]);
}
if(ans==inf) ans=-1;
cout<<ans<<endl;
return 0;
}