日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

P2387-[NOI2014]魔法森林【LCT】

發布時間:2023/12/3 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 P2387-[NOI2014]魔法森林【LCT】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

話說LCTLCTLCTSplaySplaySplay和平時寫的SplaySplaySplay差別好大,調了我半天


正題

題目鏈接:[https://www.luogu.com.cn/problem/P2387


題目大意

nnn個點mmm條邊有a,ba,ba,b兩個值,求一條路徑從1?>n1->n1?>n使得路徑上最大的aaa加上最大的bbb最小。


解題思路

我們可以將邊按照aaa排序,然后枚舉最大的aaa值。此時我們需要維護1?>n1->n1?>n路徑上最小的bbb值,要支持動態插邊。

考慮使用LCTLCTLCT,對于一條(x,y,w)(x,y,w)(x,y,w)的邊,我們查詢目前x,yx,yx,y之間路徑上的最大邊,如果該值比www大,我們斷開最大邊,連接該邊,否則不連接即可。


codecodecode

#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=2e5+10; struct node{int x,y,a,b; }a[N]; int n,m,val[N],sum[N],from[N],fa[N],ans; struct Line_Cut_Tree{#define ls t[x][0]#define rs t[x][1]int t[N][2],fa[N];bool r[N];void PushR(int x){r[x]^=1;swap(ls,rs);}void PushDown(int x){if(r[x]){r[x]=0;PushR(ls);PushR(rs);}}bool Nroot(int x){return fa[x]&&(t[fa[x]][0]==x||t[fa[x]][1]==x);}void PushUp(int x){sum[x]=val[x];from[x]=x;if(ls&&sum[ls]>sum[x]) sum[x]=sum[ls],from[x]=from[ls];if(rs&&sum[rs]>sum[x]) sum[x]=sum[rs],from[x]=from[rs];}void Rotate(int x){int y=fa[x],z=fa[y],k=(t[y][1]==x),w=t[x][!k];if(Nroot(y)) t[z][t[z][1]==y]=x;t[x][!k]=y;t[y][k]=w;if(w) fa[w]=y;fa[y]=x;fa[x]=z;PushUp(y);PushUp(x);return;}void Updata(int x){if(Nroot(x))Updata(fa[x]);PushDown(x);}void Splay(int x){int y=x,z=0;Updata(x);while(Nroot(x)){y=fa[x];z=fa[y];if(Nroot(y))Rotate((t[y][0]==x)^(t[z][0]==y)?x:y);Rotate(x);}PushUp(x);return;}void Access(int x){for(int y=0;x;x=fa[y=x])Splay(x),rs=y,PushUp(x);return;}void MakeRoot(int x){Access(x);Splay(x);PushR(x);return;}int Split(int x,int y){MakeRoot(x);Access(y);Splay(y);return from[y];}void Link(int x,int y){MakeRoot(x);fa[x]=y;Access(x);return;}void Cut(int x,int y){MakeRoot(y);Access(x);Splay(x);fa[ls]=0;ls=0;PushUp(x);return;}#undef ls#undef rs }LCT; int Find(int x) {return fa[x]==x?x:(fa[x]=Find(fa[x]));} bool cMp(node x,node y) {return x.a<y.a;} int main() {scanf("%d%d",&n,&m);ans=2147483647;for(int i=1;i<=n;i++)fa[i]=i;for(int i=1;i<=m;i++)scanf("%d%d%d%d",&a[i].x,&a[i].y,&a[i].a,&a[i].b);sort(a+1,a+1+m,cMp);for(int i=1;i<=m;i++)val[i+n]=sum[i+n]=a[i].b,from[i+n]=i+n;for(int i=1;i<=m;i++){int Fa=Find(a[i].x),Fb=Find(a[i].y);bool line=1;if(Fa==Fb){int p=LCT.Split(a[i].x,a[i].y);if(sum[p]>a[i].b)LCT.Cut(a[p-n].x,p),LCT.Cut(a[p-n].y,p);else line=0;}else fa[Fa]=Fb;if(line) LCT.Link(a[i].x,i+n),LCT.Link(a[i].y,i+n);if(Find(1)==Find(n))ans=min(ans,a[i].a+sum[LCT.Split(1,n)]);}if(ans==2147483647) printf("-1");else printf("%d",ans); }

總結

以上是生活随笔為你收集整理的P2387-[NOI2014]魔法森林【LCT】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。