题目
思路
最大值最小?还跟路径有关?当然是维护最小生成树啦
只有一个值很简单:暴力加边并查集判断连通性,当1,n第一次连通的时候答案一定是最小的
可是现在有两个值怎么办呢
考虑按a排序,维护以b为关键字的最小生成树,答案就是1,n路径上最大值+当前的a
然而b是无序的,所以维护这个最小生成树需要找到环上最大的边断开然后加入新边,所以我们要用LCT
那么问题来了,怎么维护边权?
在每条边中间加一个点代表边权就行了
代码
#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f,N=2e5+77;
int mx[N],id[N],ch[N][2],rev[N],fa[N],n,m,w[N],Q[N],ans=inf;
struct E
{
int u,v,a,b;
}e[N];
bool cmp(E x,E y)
{
return x.a<y.a||(x.a==y.a&&x.b<y.b);
}
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 update(int x)
{
id[x]=x; mx[x]=w[x];
if(ch[x][0]&&mx[ch[x][0]]>mx[x]) mx[x]=mx[ch[x][0]],id[x]=id[ch[x][0]];
if(ch[x][1]&&mx[ch[x][1]]>mx[x]) mx[x]=mx[ch[x][1]],id[x]=id[ch[x][1]];
}
void pushdown(int x)
{
if(!rev[x]) return;
rev[ch[x][0]]^=1; rev[ch[x][1]]^=1;
swap(ch[x][0],ch[x][1]);
rev[x]=0;
}
void rotate(int x)
{
int y=fa[x],z=fa[y],l=get(x),r=l^1;
if(!isroot(y)) ch[z][get(y)]=x;
fa[x]=z; fa[y]=x; fa[ch[x][r]]=y; ch[y][l]=ch[x][r]; ch[x][r]=y;
update(x); update(y);
}
void splay(int x)
{
int top=0;
Q[++top]=x;
for(int i=x; !isroot(i); i=fa[i]) Q[++top]=fa[i];
while(top) pushdown(Q[top--]);
while(!isroot(x))
{
int y=fa[x],z=fa[y],d1=ch[y][1]==x,d2=ch[z][1]==y;
if(!isroot(y))
{
if(d1==d2) rotate(y),rotate(x); else rotate(x),rotate(x);
}
else rotate(x);
}
update(x);
}
void access(int x)
{
for(int t=0; x; t=x,x=fa[x])
{
splay(x),ch[x][1]=t,update(x);
if(t) fa[t]=x;
}
}
void makeroot(int x)
{
access(x); splay(x); rev[x]^=1;
}
void split(int x,int y)
{
makeroot(x); access(y); splay(y);
}
void link(int x,int y)
{
makeroot(x); fa[x]=y;
}
void cut(int x,int y)
{
split(x,y); ch[y][0]=fa[x]=0; update(y);
}
int findroot(int x)
{
access(x); splay(x);
while(ch[x][0]) pushdown(x),x=ch[x][0];
return x;
}
bool check(int x,int y)
{
makeroot(x);
return findroot(y)==x;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1; i<=m; i++) scanf("%d%d%d%d",&e[i].u,&e[i].v,&e[i].a,&e[i].b);
sort(e+1,e+m+1,cmp);
for(int i=1; i<=m; i++)
{
w[i+n]=e[i].b;
if(e[i].u==e[i].v) continue;
if(!check(e[i].u,e[i].v)) link(e[i].u,i+n),link(i+n,e[i].v);
else
{
split(e[i].u,e[i].v);
int yjy=id[e[i].v],aii=mx[e[i].v];
if(aii<=e[i].b) continue;
splay(yjy);
fa[ch[yjy][0]]=fa[ch[yjy][1]]=0;
link(e[i].u,i+n),link(i+n,e[i].v);
}
if(check(1,n))
{
split(1,n); ans=min(ans,mx[n]+e[i].a);
}
}
if(ans==inf) printf("-1");else printf("%d",ans);
}