此题可以用spfa,也可以用LCT。
可spfa跑得比LCT快……
学习了一下怎么把边权变成点权:
新建一个点表示边,这个点的点权就是边权值
原来的点的权值为0(根据题目需要可以为其他值)
添加一条边时,连接两端的点
删除一条边时,需要找到这条边对应的点编号,两端删除
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
struct node {
int u,v,a,b;
bool operator<(const node &res) const{
return a<res.a;
}
} edge[100005];
int FA[50005];
int val[150005],mx[150005],po[150005];
int ch[150005][2],fa[150005];
bool reversed[150005];
int sta[150005],top;
int n,m,ans=1e9;
inline int read() {
char ch=0;int sum=0;
while (ch>'9'||ch<'0') ch=getchar();
while (ch>='0'&&ch<='9') sum=sum*10+ch-'0',ch=getchar();
return sum;
}
int find(int x) {
if (FA[x]!=x) FA[x]=find(FA[x]);
return FA[x];
}
inline void Union(int x,int y) {
FA[find(x)]=find(y);
}
inline void reverse(int x) {
swap(ch[x][0],ch[x][1]);
reversed[x]^=1;
}
inline void pushdown(int x) {
if (reversed[x]) {
if (ch[x][0]) reverse(ch[x][0]);
if (ch[x][1]) reverse(ch[x][1]);
reversed[x]=0;
}
}
inline void pushup(int x) {
int pp=x,tmp=val[x];
if (mx[ch[x][1]]>tmp) pp=po[ch[x][1]],tmp=mx[ch[x][1]];
if (mx[ch[x][0]]>tmp) pp=po[ch[x][0]],tmp=mx[ch[x][0]];
po[x]=pp;mx[x]=tmp;
}
inline bool notroot(int x) {
return (ch[fa[x]][0]==x)||(ch[fa[x]][1]==x);
}
inline void rotate(int x) {
int fa1=fa[x],fa2=fa[fa1],side=(ch[fa1][1]==x),c=ch[x][side^1];
fa[x]=fa2;if (notroot(fa1)) ch[fa2][ch[fa2][1]==fa1]=x;
ch[fa1][side]=c;if (c) fa[c]=fa1;
fa[fa1]=x;ch[x][side^1]=fa1;
pushup(fa1);pushup(x);
}
inline void splay(int x) {
int u=x,top=0;
while (notroot(u)) sta[++top]=u,u=fa[u];
sta[++top]=u;
while (top) pushdown(sta[top--]);
while (notroot(x)) {
int fa1=fa[x],fa2=fa[fa1];
if (notroot(fa1)) {
if ((ch[fa2][0]==fa1)^(ch[fa1][0]==x)) rotate(x);
else rotate(fa1);
}
rotate(x);
}
}
inline void access(int x) {
int u=0;
while (x!=0) {
splay(x);
ch[x][1]=u;
pushup(x);
u=x;
x=fa[x];
}
}
inline void makeroot(int x) {
access(x);splay(x);
reverse(x);
}
inline int findroot(int x) {
access(x);splay(x);
while (ch[x][0]) pushdown(x),x=ch[x][0];
splay(x);
return x;
}
inline void split(int x,int y) {
makeroot(x);
access(y);splay(y);
}
inline void link(int x,int y) {
makeroot(x);
if (findroot(y)!=x) fa[x]=y;
}
inline void cut(int x,int y) {
makeroot(x);
if (findroot(y)==x && fa[y]==x && ch[x][1]!=0) {
fa[y]=ch[x][0]=0;
pushup(x);
}
}
inline void addedge(int i) {
int u=edge[i].u,v=edge[i].v;
if (find(u)!=find(v)) {
Union(u,v);
val[i+n]=mx[i+n]=edge[i].b;
po[i+n]=i+n;
link(u,i+n);
link(v,i+n);
}
else {
split(u,v);
if (edge[i].b<mx[v]) {
int w=po[v];
cut(w,edge[w-n].u);
cut(w,edge[w-n].v);
val[i+n]=mx[i+n]=edge[i].b;
po[i+n]=i+n;
link(u,i+n);
link(v,i+n);
}
}
}
int main() {
n=read(),m=read();
for (int i=1;i<=m;i++) {
edge[i].u=read();edge[i].v=read();
edge[i].a=read();edge[i].b=read();
}
sort(edge+1,edge+m+1);
for (int i=1;i<=n;i++) FA[i]=po[i]=i;
for (int i=1;i<=m;i++) {
addedge(i);
while (i<m && edge[i].a==edge[i+1].a) addedge(++i);
if (find(1)==find(n)) {
split(1,n);
ans=min(ans,edge[i].a+mx[n]);
}
}
if (ans==1e9) puts("-1");
else printf("%d",ans);
return 0;
}