[loj2245]魔法森林
枚举携带的"A型守护精灵"数$A_{0}$,那么即只能经过$A_{i}\le A_{0}$的边,并最小化1到$n$路径上最大的$B_{i}$
将所有边按照$A_{i}$从小到大排序,那么前者即不断加入边,后者通过LCT维护$B_{i}$的最小生成树即可
具体的,将每一条边拆成一个点,向对应的两端点连边,加入一条边时查询对应环(若不产生环则直接加入)上$B_{i}$最大的边并替换即可
时间复杂度为$o(m\log m)$,可以通过
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 150005 4 struct Data{ 5 int x,y,a,b; 6 bool operator < (const Data &k)const{ 7 return a<k.a; 8 } 9 }e[N]; 10 multiset<int>S; 11 int n,m,ans,st[N],fa[N],sz[N],rev[N],val[N],mx[N],ch[N][2]; 12 int which(int k){ 13 return ch[fa[k]][1]==k; 14 } 15 int check(int k){ 16 return ch[fa[k]][which(k)]==k; 17 } 18 int get_max(int x,int y){ 19 if (e[x].b>e[y].b)return x; 20 return y; 21 } 22 void upd(int k){ 23 rev[k]^=1; 24 swap(ch[k][0],ch[k][1]); 25 } 26 void up(int k){ 27 sz[k]=sz[ch[k][0]]+sz[ch[k][1]]+1; 28 mx[k]=get_max(get_max(mx[ch[k][0]],mx[ch[k][1]]),val[k]); 29 } 30 void down(int k){ 31 if (rev[k]){ 32 if (ch[k][0])upd(ch[k][0]); 33 if (ch[k][1])upd(ch[k][1]); 34 rev[k]=0; 35 } 36 } 37 void rotate(int k){ 38 int f=fa[k],g=fa[f],p=which(k); 39 fa[k]=g; 40 if (check(f))ch[g][which(f)]=k; 41 fa[ch[k][p^1]]=f,ch[f][p]=ch[k][p^1]; 42 fa[f]=k,ch[k][p^1]=f; 43 up(f),up(k); 44 } 45 void splay(int k){ 46 for(int i=k;;i=fa[i]){ 47 st[++st[0]]=i; 48 if (!check(i))break; 49 } 50 while (st[0])down(st[st[0]--]); 51 for(int i=fa[k];check(k);i=fa[k]){ 52 if (check(i)){ 53 if (which(i)==which(k))rotate(i); 54 else rotate(k); 55 } 56 rotate(k); 57 } 58 } 59 void access(int k){ 60 int lst=0; 61 while (k){ 62 splay(k); 63 ch[k][1]=lst,up(k); 64 lst=k,k=fa[k]; 65 } 66 } 67 void make_root(int k){ 68 access(k); 69 splay(k); 70 upd(k); 71 } 72 int find_root(int k){ 73 access(k); 74 splay(k); 75 while (ch[k][0]){ 76 down(k); 77 k=ch[k][0]; 78 } 79 splay(k); 80 return k; 81 } 82 void add(int x,int y){ 83 make_root(x); 84 make_root(y); 85 fa[y]=x; 86 } 87 void del(int x,int y){ 88 make_root(x); 89 access(y); 90 splay(x); 91 fa[y]=ch[x][1]=0; 92 up(x); 93 } 94 int query(int x,int y){ 95 make_root(x); 96 if (find_root(y)!=x)return -1; 97 return mx[x]; 98 } 99 int main(){ 100 scanf("%d%d",&n,&m); 101 for(int i=1;i<=m;i++)scanf("%d%d%d%d",&e[i].x,&e[i].y,&e[i].a,&e[i].b); 102 sort(e+1,e+m+1); 103 for(int i=1;i<=m;i++)val[i+n]=mx[i+n]=i; 104 for(int i=1;i<=m;i++)add(e[i].x,i+n); 105 ans=1e9; 106 for(int i=1;i<=m;i++){ 107 int s=query(e[i].y,i+n); 108 if (s!=i){ 109 if (s>0)del(e[s].y,s+n); 110 add(e[i].y,i+n); 111 } 112 s=query(1,n); 113 if (s>0)ans=min(ans,e[i].a+e[s].b); 114 } 115 if (ans==1e9)ans=-1; 116 printf("%d\n",ans); 117 return 0; 118 }