题解:
和上一题差不多的一个思路
首先按照ai排序
然后一条条bi加进来,对bi做最小生成树(lct)
代码:
#include<bits/stdc++.h> using namespace std; const int N=2e5+5; int n,m,ans=2e9,fa[N],val[N],f[N],ch[N][2],num[N],rev[N]; struct hp{int x,y,a,b;}e[N]; int cmp(hp x,hp y){return x.a<y.a||(x.a==y.a&&x.b<y.b);} int find(int x){if (x==fa[x]) return x;return fa[x]=find(fa[x]);} int get(int x){return ch[f[x]][1]==x;} int isroot(int x){return ch[f[x]][0]!=x&&ch[f[x]][1]!=x;} void update(int x) { num[x]=x; if (ch[x][0]&&val[num[ch[x][0]]]>val[num[x]])num[x]=num[ch[x][0]]; if (ch[x][1]&&val[num[ch[x][1]]]>val[num[x]])num[x]=num[ch[x][1]]; } void pushdown(int x) { if (rev[x]) { swap(ch[x][0],ch[x][1]); rev[ch[x][0]]^=1;rev[ch[x][1]]^=1;rev[x]=0; } } void rotate(int x) { int y=f[x],z=f[y],k=get(x); if (!isroot(y)) ch[z][ch[z][1]==y]=x;f[x]=z; ch[y][k]=ch[x][k^1];f[ch[y][k]]=y; ch[x][k^1]=y;f[y]=x; update(y);update(x); } void down(int x){if (!isroot(x))down(f[x]);pushdown(x);} void splay(int x) { down(x); for (int fa;!isroot(x);rotate(x)) if (!isroot(fa=f[x]))rotate((get(x)==get(fa))?fa:x); } void access(int x){for (int t=0;x;t=x,x=f[x])splay(x),ch[x][1]=t,update(x);} void reverse(int x){access(x);splay(x);rev[x]^=1;} void link(int x,int y){reverse(x);f[x]=y;splay(x);} void cut(int x,int y){reverse(x);access(y);splay(y);ch[y][0]=f[x]=0;} int query(int x,int y){reverse(x);access(y);splay(y);return num[y];} int main() { scanf("%d%d",&n,&m); for (int i=1;i<=m;i++)scanf("%d%d%d%d",&e[i].x,&e[i].y,&e[i].a,&e[i].b); sort(e+1,e+m+1,cmp); for (int i=1;i<=m;i++)val[n+i]=e[i].b; for (int i=1;i<=n;i++)fa[i]=i; for (int i=1;i<=m;i++) { int fx=find(e[i].x),fy=find(e[i].y); if (fx!=fy)link(e[i].x,n+i),link(n+i,e[i].y),fa[fx]=fy; else { int k=query(e[i].x,e[i].y); if (val[k]>e[i].b) { cut(e[k-n].x,k);cut(k,e[k-n].y); link(e[i].x,n+i);link(n+i,e[i].y); } } if (find(1)==find(n))ans=min(ans,e[i].a+val[query(1,n)]); } if (ans<2e9) printf("%d ",ans); else puts("-1"); }