和最小差值生成树差不多
都是用lct维护生成树的题目
本题可以以a排序,再维护b(通常这种二维变量的题都差不多这样,先排序一维)
然后我tm竟然rotate手误打错了一点...调了好久..
然后关于pushup:关于最大值,最小值一类的信息要在pushup中赋初值,而异或和之类的可以不用
就是说不可以用引用中写法的来写..
#include<bits/stdc++.h> using namespace std; const int N=5e4+7; const int M=1e5+7; int n,m,st[N+M],tot,ans=1<<30,w[N+M]; struct edge{ int a,b,u,v; bool operator <(const edge &x)const { return a<x.a; } }e[M]; struct tree{ int ch[2],fa,mx=-1,id=-1; bool rev; }t[N+M]; void pushup(int x) { t[x].mx=w[x],t[x].id=x; if(t[x].ch[0]&&t[t[x].ch[0]].mx>t[x].mx) t[x].mx=t[t[x].ch[0]].mx,t[x].id=t[t[x].ch[0]].id; if(t[x].ch[1]&&t[t[x].ch[1]].mx>t[x].mx) t[x].mx=t[t[x].ch[1]].mx,t[x].id=t[t[x].ch[1]].id; } void rev(int x){ swap(t[x].ch[0],t[x].ch[1]); t[x].rev^=1; } void pushdown(int x){ if(t[x].rev){ if(t[x].ch[0])rev(t[x].ch[0]); if(t[x].ch[1])rev(t[x].ch[1]); t[x].rev=0; } } bool nroot(int x){ return (t[t[x].fa].ch[0]==x)||(t[t[x].fa].ch[1]==x); } void rotate(int x){ int y=t[x].fa; int z=t[y].fa; bool k=t[y].ch[1]==x; if(nroot(y))t[z].ch[t[z].ch[1]==y]=x; t[x].fa=z; t[y].ch[k]=t[x].ch[k^1]; t[t[x].ch[k^1]].fa=y; t[x].ch[k^1]=y; t[y].fa=x; pushup(y); pushup(x); } void splay(int x){ int y=0,z=x; st[++y]=z; while(nroot(z))st[++y]=z=t[z].fa; while(y)pushdown(st[y--]); while(nroot(x)){ y=t[x].fa; z=t[y].fa; if(nroot(y)) (t[y].ch[1]==x)^(t[z].ch[1]==y)?rotate(x):rotate(y); rotate(x); } } void access(int x){ for(int y=0;x;y=x,x=t[x].fa){ splay(x); t[x].ch[1]=y; pushup(x); } } void makeroot(int x){ access(x); splay(x); rev(x); } void split(int x,int y){ makeroot(x); access(y); splay(y); } int findroot(int x){ access(x); splay(x); while(t[x].ch[0])x=t[x].ch[0]; splay(x); return x; } void link(int x,int y){ splay(x); t[x].fa=y; } bool check(int x,int y){ makeroot(x); return findroot(y)==x; } int main(){ cin>>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+1+m); for(int i=1;i<=m;i++){ int u=e[i].u; int v=e[i].v; //t[i+n].mx=e[i].b,t[i+n].id=i+n; w[i+n]=e[i].b; if(u==v)continue; if(!check(u,v)){ link(u,i+n),link(i+n,v); } else { split(u,v); int now=t[v].id,maxx=t[v].mx; if(e[i].b>maxx)continue; splay(now),t[t[now].ch[0]].fa=t[t[now].ch[1]].fa=0; link(u,i+n),link(i+n,v); } if(check(1,n)){ split(1,n); ans=min(ans,t[n].mx+e[i].a); } } if(ans==1<<30)puts("-1"); else printf("%d ",ans); return 0; }