正题
P2387
题目大意
给你一个图,每条边有两个全职a,b,现在让你找一条从1到n的路径使得max(a)+max(b)最小
解题思路
对a进行排序,枚举a的最大值,然后取b最小的边,找1到n的最短路径
找最短路径可以用LCT求,对于连边,如果不在一个连通分量内,就直接连起来
否则在两个端点的路径上找一条最大的边,将其断掉,然后连上该边(如果不是更优则不操作)
code
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define N 100100
using namespace std;
ll n,m,g,x,y,now,ans,top,d[N<<1],v[N<<1];
struct line
{ll x,y,a,b;
}l[N];
bool cmp(line a,line b)
{return a.a<b.a;
}
struct LCT
{#define ls son[x][0]#define rs son[x][1]ll p[N<<1],mx[N<<1],fa[N<<1],son[N<<1][2];bool NR(ll x){return fa[x]&&(son[fa[x]][0]==x||son[fa[x]][1]==x);}bool IRS(ll x){return son[fa[x]][1]==x;}void pushr(ll x){swap(ls,rs);p[x]^=1;return;}void push_down(ll x){if(p[x]){if(ls)pushr(ls);if(rs)pushr(rs);p[x]=0;}return;}void push_up(ll x){if(ls&&v[mx[ls]]>=v[mx[rs]]&&v[mx[ls]]>=v[x])mx[x]=mx[ls];else if(rs&&v[mx[rs]]>=v[mx[ls]]&&v[mx[rs]]>=v[x])mx[x]=mx[rs];else mx[x]=x;return;}void rotate(ll x){ll y=fa[x],z=fa[y],k=IRS(x),g=son[x][!k];if(NR(y))son[z][IRS(y)]=x;if(g)fa[g]=y;son[x][!k]=y;son[y][k]=g;fa[x]=z;fa[y]=x;push_up(y);return;}void Splay(ll x){ll y=x;d[++top]=y;while(NR(y))y=fa[y],d[++top]=y;while(top)push_down(d[top--]);while(NR(x)){if(NR(fa[x])){if(IRS(x)==IRS(fa[x]))rotate(fa[x]);else rotate(x);}rotate(x);}push_up(x);return;}void access(ll x){for(ll y=0;x;x=fa[y=x])Splay(x),rs=y,push_up(x);return;}void make_root(ll x){access(x);Splay(x);pushr(x);return;}ll find_root(ll x){access(x);Splay(x);while(ls)push_down(x),x=ls;Splay(x);return x;}void Split(ll x,ll y){make_root(x);access(y);Splay(y);return;}void link(ll x,ll y){make_root(x);if(find_root(y)!=x)fa[x]=y;return;}void cut(ll x,ll y){make_root(x);if(find_root(y)==x&&fa[y]==x&&!son[y][0]){rs=fa[y]=0;push_up(x);}return;}
}T;
int main()
{scanf("%lld%lld",&n,&m);for(ll i=1;i<=n+m;++i)T.mx[i]=i;for(ll i=1;i<=m;++i)scanf("%lld%lld%lld%lld",&l[i].x,&l[i].y,&l[i].a,&l[i].b);sort(l+1,l+1+m,cmp);ll i=1;ans=1e15;while(i<=m){g=l[i].a;while(l[i].a==g&&i<=m){x=l[i].x;y=l[i].y;v[i+n]=l[i].b;if(T.find_root(x)==T.find_root(y)){T.Split(x,y);now=T.mx[y];if(v[now]>l[i].b){T.cut(l[now-n].x,now);T.cut(l[now-n].y,now);T.link(x,i+n);T.link(y,i+n);}}else{T.link(x,i+n);T.link(y,i+n);}i++;}if(T.find_root(1)==T.find_root(n)){T.Split(1,n);ans=min(ans,g+v[T.mx[n]]);}}if(ans<1e15)printf("%lld",ans);else puts("-1");return 0;
}