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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

YBTOJ洛谷P2387: 魔法森林(LCT)

發(fā)布時(shí)間:2023/12/3 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 YBTOJ洛谷P2387: 魔法森林(LCT) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

解析

LCT從板子到算法的入門題吧
有一些不知道的很實(shí)用的技巧

把邊按a排序從小到大加入邊
那么我們只需要維護(hù)當(dāng)前1-n路徑上的b的最小值即可
如果這條邊兩端點(diǎn)本來不連通,就直接link
否則找到路徑上b最大的一條邊,斷掉,再加入當(dāng)前邊(前提是b最大的邊的b大于當(dāng)前邊)

實(shí)現(xiàn)上,可以把每條邊轉(zhuǎn)化成一個(gè)虛點(diǎn)
十分方便

代碼

#include<bits/stdc++.h> using namespace std; #define ll long long const int N=2e5+100; const int mod=1e9+7; const double eps=1e-9; inline ll read() {ll x(0),f(1);char c=getchar();while(!isdigit(c)) {if(c=='-')f=-1;c=getchar();}while(isdigit(c)) {x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f; }int n,m;#define ls(o) tr[o][0] #define rs(o) tr[o][1] int tr[N][2],f[N],rev[N],val[N],mx[N]; inline bool isroot(int x) {return tr[f[x]][0]!=x&&tr[f[x]][1]!=x; } inline bool which(int x) {return tr[f[x]][1]==x; } inline void pushup(int x) {if(x){mx[x]=x;if(ls(x)&&val[mx[ls(x)]]>val[mx[x]]) mx[x]=mx[ls(x)];if(rs(x)&&val[mx[rs(x)]]>val[mx[x]]) mx[x]=mx[rs(x)];}return; } inline void tag(int x) {if(x) {rev[x]^=1;swap(tr[x][0],tr[x][1]);} } inline void pushdown(int x) {if(rev[x]){rev[x]=0;tag(tr[x][0]);tag(tr[x][1]);}return; } void debug(int x) {if(!x) return;pushdown(x);debug(tr[x][0]);printf("debug: x=%d ls=%d rs=%d\n",x,tr[x][0],tr[x][1]);debug(tr[x][1]);return; } inline void rotate(int x) {int fa=f[x],gfa=f[fa];int d=which(x),son=tr[x][d^1];f[x]=gfa;if(!isroot(fa)) tr[gfa][which(fa)]=x;f[fa]=x;tr[x][d^1]=fa;if(son){f[son]=fa;}tr[fa][d]=son;pushup(fa);pushup(x);return; } int zhan[N]; inline void splay(int x) {int y=x,top=0;zhan[++top]=y;while(!isroot(y)) zhan[++top]=y=f[y];while(top) pushdown(zhan[top--]);for(int fa; fa=f[x],!isroot(x); rotate(x)) {if(!isroot(fa)) which(fa)==which(x)?rotate(fa):rotate(x);}return; } inline void access(int x) {for(int y(0); x; y=x,x=f[x]) {splay(x);tr[x][1]=y;pushup(x);if(y) f[y]=x;}return; } inline void makeroot(int x) {access(x);splay(x);tag(x);return; } inline int findroot(int x) {access(x);splay(x);while(pushdown(x),tr[x][0]) x=tr[x][0];splay(x);return x; } inline void link(int x,int y) {makeroot(x);if(findroot(y)==x) return;f[x]=y;pushup(y);//printf("link: %d -> %d\n",x,y); } inline void cut(int x,int y) {makeroot(x);access(y);splay(y);if(tr[y][0]!=x||tr[x][1]) return;tr[y][0]=f[x]=0;pushup(y);return; } inline void split(int x,int y){//y is fathermakeroot(x);access(y);splay(y);return; } struct edge{int x,y,a,b;bool operator < (const edge oth)const{return a<oth.a;} }e[N]; int main() { #ifndef ONLINE_JUDGE//freopen("a.in","r",stdin);//freopen("a.out","w",stdout); #endifn=read();m=read();for(int i=1;i<=m;i++) e[i]=(edge){(int)read(),(int)read(),(int)read(),(int)read()};sort(e+1,e+1+m);int ans(2e9);for(int i=1;i<=m;i++){int x=e[i].x,y=e[i].y,w=e[i].b;val[i+n]=w;//printf("\nid=%d (%d %d) w=%d (a=%d)\n",i+n,x,y,w,e[i].a);if(findroot(x)!=findroot(y)) link(x,n+i),link(y,n+i);else{split(x,y);int now=mx[y];if(val[now]>w){splay(now);f[tr[now][0]]=0;tr[now][0]=0;f[tr[now][1]]=0;tr[now][1]=0;pushup(now);link(n+i,x);link(n+i,y);}}if(findroot(1)==findroot(n)){split(1,n);ans=min(ans,val[mx[n]]+e[i].a);//debug(n);}}printf("%d\n",ans<2e9?ans:-1);return 0; }

總結(jié)

以上是生活随笔為你收集整理的YBTOJ洛谷P2387: 魔法森林(LCT)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。