题目
emmm我觉着有点迷。。先将m条边按a从小到大排序。
最长边最小 这个路径在最小生成树上。
1.还没构成一颗生成树时,u v已经有路径相连 但新边的y小于u v原来路径的最长边。一定要替换。这是毋庸置疑的,虽然新边的 x 变大了,但此时还没构成生成树,还要加入x更大的边。所以此时x大了也无所谓啊。
2.此时已经构成了一颗生成树。其实下面的代码(在现有生成树的基础上换边 )就是把每一种可能作为答案的枚举一遍,但明显不是最优的直接排除了。 比如:原生成树为A a大了 b也大了,首先这颗生成树肯定是不合法的,它对后面的有影响吗?没有一颗生成树是以它为基础变得,因为我们为为什么不在A的基础上删掉一条边 加上一条边呢。、、
其实 。我说不清。因为我理解的也不是很透彻。所以我准备记住。呜呜呜呜。
#include<cstdio>
#include<algorithm>
using namespace std;
inline int rd(){
char ch=getchar();int x=0,op=1;
for(;!isdigit(ch);ch=getchar()) if(ch=='-') op=-1;
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
return x*op;
}
const int N=5e4+5,M=1e5+5;
struct node{int x,y,a,b;}e[M];
inline int cmp(node A,node B){return A.a<B.a;}
int f[N+M],ch[N+M][2],st[N+M],tag[N+M],val[N+M],mx[N+M],F[N];
inline int seek(int x){return (x==F[x])?(x):(F[x]=seek(F[x]));}
inline void combine(int x,int y){F[seek(x)]=seek(y);}
inline void pushup(int x){
mx[x]=val[x];
if(e[mx[ch[x][0]]].b>e[mx[x]].b) mx[x]=mx[ch[x][0]];
if(e[mx[ch[x][1]]].b>e[mx[x]].b) mx[x]=mx[ch[x][1]];
}
inline void pushdown(int x){
if(!tag[x]) return;
swap(ch[ch[x][0]][0],ch[ch[x][0]][1]),tag[ch[x][0]]^=1;
swap(ch[ch[x][1]][0],ch[ch[x][1]][1]),tag[ch[x][1]]^=1;
tag[x]=0;
}
inline int notroot(int x){
return ch[f[x]][0]==x||ch[f[x]][1]==x;
}
inline void route(int x){
int y=f[x],z=f[y],w=(ch[y][1]==x);
if(notroot(y)) ch[z][ch[z][1]==y]=x;
f[x]=z;
ch[y][w]=ch[x][w^1];if(ch[y][w]) f[ch[y][w]]=y;
ch[x][w^1]=y,f[y]=x;
pushup(y),pushup(x);
}
inline void splay(int x){
int y=x,num=0;st[++num]=y;
while(notroot(y)) st[++num]=(y=f[y]);
while(num) pushdown(st[num--]);
if(!notroot(x)) return;
for(int fa=f[x];notroot(x);route(x),fa=f[x])
if(notroot(fa)) ((ch[fa][1]==x)^(ch[f[fa]][1]==fa))?route(x):route(fa);
}
inline void access(int x){
for(int y=0;x;x=f[y=x])
splay(x),ch[x][1]=y,pushup(x);
}
inline void makeroot(int x){
access(x),splay(x);
swap(ch[x][0],ch[x][1]),tag[x]^=1;
}
inline void split(int x,int y){
makeroot(x),access(y),splay(y);
}
inline void link(int x,int y){
makeroot(x),f[x]=y;
}
inline void cut(int x,int y){
split(x,y),f[x]=ch[y][0]=0,pushup(y);
}
int main(){
int n=rd(),m=rd();
for(int i=1;i<=n;++i) F[i]=i;
for(int i=1;i<=m;++i) e[i]=(node){rd(),rd(),rd(),rd()},val[i+n]=i;
sort(e+1,e+m+1,cmp);
int ans=M;
for(int i=1,x,y;i<=m;++i){
x=e[i].x,y=e[i].y;
if(seek(x)!=seek(y)) link(x,i+n),link(y,i+n),combine(x,y);
else{
split(x,y);int id=mx[y];
if(e[id].b>e[i].b){
cut(e[id].x,id+n),cut(e[id].y,id+n);
link(x,i+n),link(y,i+n);
}
}
if(seek(1)==seek(n)) split(1,n),ans=min(ans,e[i].a+e[mx[n]].b);
}
printf("%d\n",(ans==M)?-1:ans);
}