[NOI2014]魔法森林
题解:
lct维护生成树
首先先把a按照权值从小到大排序
然后维护路径间b的最小值(其实就是满足树的性质)
如果这两点之间连边了,我们就找到其中的最大边,判断一下他和当前点的大小关系
边权变成点权处理就可以了
代码:
#include <bits/stdc++.h> using namespace std; #define N 200000 struct re{ int a,b,c,d; }a[N*2]; int v[N],data[N],data2[N],n,m; int leftson[N],rightson[N],fa[N]; bool rev[N]; bool cmp(re x,re y) { return(x.c<y.c); } void updata(int x) { data[x]=max(max(data[leftson[x]],data[rightson[x]]),v[x]); if (data[x]==v[x]) data2[x]=x; else if (data[x]==data[leftson[x]]) data2[x]=data2[leftson[x]]; else data2[x]=data2[rightson[x]]; } void down(int x) { if (!rev[x]) return; swap(leftson[x],rightson[x]); rev[x]=0; rev[leftson[x]]^=1; rev[rightson[x]]^=1; } bool pd(int x) { if (leftson[fa[x]]!=x&&rightson[fa[x]]!=x) return(0); else return(1); } void rotate(int x,int y) { int father=fa[x]; if (y==1) { rightson[father]=leftson[x]; if (leftson[x]) fa[leftson[x]]=father; } else { leftson[father]=rightson[x]; if (rightson[x]) fa[rightson[x]]=father; } fa[x]=fa[father]; if (pd(father)) { if (leftson[fa[x]]==father) leftson[fa[x]]=x; else rightson[fa[x]]=x; } if (y==1) leftson[x]=father; else rightson[x]=father; fa[father]=x; updata(father); updata(x); } void dfs(int x) { if (pd(x)) dfs(fa[x]); down(x); } void splay(int x) { dfs(x); int father=fa[x]; while (pd(x)) { if (!pd(father)) { if (x==leftson[father]) rotate(x,2); else rotate(x,1); } else { if (father==leftson[fa[father]]) if (x==leftson[father]) rotate(father,2),rotate(x,2); else rotate(x,1),rotate(x,2); else if (x==rightson[father]) rotate(father,1),rotate(x,1); else rotate(x,2),rotate(x,1); } father=fa[x]; } } void access(int x) { for (int y=0;x;y=x,x=fa[x]) splay(x),rightson[x]=y,updata(x); } void makeroot(int x) { access(x); splay(x); rev[x]^=1; } int findroot(int x) { access(x); splay(x); while (leftson[x]) x=leftson[x]; return x; } void split(int x,int y) { makeroot(x); access(y); splay(y); } bool find(int x,int y) { makeroot(x); if (findroot(y)!=x) return(0); else return(1); } void link(int x,int y) { makeroot(x); if (findroot(y)!=x) fa[x]=y; } void cut(int x,int y) { makeroot(x); if (findroot(y)==x&&fa[x]==y&&!rightson[x]) { fa[x]=leftson[y]=0; updata(y); } } int main() { cin>>n>>m; for (int i=1;i<=m;i++) cin>>a[i].a>>a[i].b>>a[i].c>>a[i].d; sort(a+1,a+m+1,cmp); int ans=1e9; for (int i=1;i<=m;i++) { int x=a[i].a,y=a[i].b; if (find(a[i].a,a[i].b)) { split(x,y); int tmp=data2[y]; if (a[i].d<data[y]) { cut(tmp,a[tmp-n].a); cut(tmp,a[tmp-n].b); link(i+n,a[i].a); link(i+n,a[i].b); v[i+n]=a[i].d; } } else { link(i+n,a[i].a); link(i+n,a[i].b); v[i+n]=a[i].d; } if (find(1,n)) { split(1,n); ans=min(ans,data[n]+a[i].c); } } if (ans==1e9) cout<<-1; else cout<<ans; return 0; }