P4172-[WC2006]水管局长【LCT,最小生成树】
生活随笔
收集整理的這篇文章主要介紹了
P4172-[WC2006]水管局长【LCT,最小生成树】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
正題
題目鏈接:https://www.luogu.com.cn/problem/P4172
題目大意
nnn個點的一張圖,有兩個操作
解題思路
顯然這條邊一定是在最小生成樹上的,所以我們需要維護支持刪邊的最小生成樹。
顯然LCTLCTLCT無法支持刪除,但是注意到只有刪除操作,所以我們反著做的話就變成了加邊操作,用LCTLCTLCT維護即可。
codecodecode
#include<cstdio> #include<cstring> #include<algorithm> #include<stack> #define mp(x,y) make_pair(x,y) using namespace std; const int N=2e5+10,inf=2147483647; int n,m,t,ans[N]; int from[N],w[N],val[N]; pair<pair<int,int> ,int>lk[N]; struct node{int x,y,w,id;bool del; }e[N]; struct Query{int op,x,y; }q[N]; struct LCT{stack<int> s;int fa[N],t[N][2],r[N];void PushUp(int x){from[x]=x;w[x]=val[x];if(t[x][0]&&w[t[x][0]]>w[x])w[x]=w[t[x][0]],from[x]=from[t[x][0]];if(t[x][1]&&w[t[x][1]]>w[x])w[x]=w[t[x][1]],from[x]=from[t[x][1]];return;}bool Nroot(int x){return fa[x]&&(t[fa[x]][0]==x||t[fa[x]][1]==x);}bool Direct(int x){return t[fa[x]][1]==x;}void Rev(int x){swap(t[x][0],t[x][1]);r[x]^=1;}void PushDown(int x){if(r[x])Rev(t[x][0]),Rev(t[x][1]),r[x]=0;return;}void Rotate(int x){int y=fa[x],z=fa[y];int xs=Direct(x),ys=Direct(y);int w=t[x][xs^1];if(Nroot(y))t[z][ys]=x;t[x][xs^1]=y;t[y][xs]=w;if(w)fa[w]=y;fa[y]=x;fa[x]=z;PushUp(y);PushUp(x);}void Splay(int x){int now=x;s.push(x);while(Nroot(now))now=fa[now],s.push(now);while(!s.empty())PushDown(s.top()),s.pop();while(Nroot(x)){int y=fa[x];if(!Nroot(y))Rotate(x);else if(Direct(x)==Direct(y))Rotate(y),Rotate(x);else Rotate(x),Rotate(x);}return;}void Access(int x){for(int y=0;x;y=x,x=fa[x])Splay(x),t[x][1]=y,PushUp(x);return; }void MakeRoot(int x){Access(x);Splay(x);Rev(x);return;}void Split(int x,int y){MakeRoot(x);Access(y);Splay(y);return;}void Link(int x,int y){MakeRoot(x);fa[x]=y;Access(x);return;}void Cut(int x,int y){MakeRoot(x);Access(y);Splay(y);fa[t[y][0]]=0;t[y][0]=0;PushUp(y);return;} }LCT; struct unionfind{int fa[N];int find(int x){return (fa[x]==x)?x:(fa[x]=find(fa[x]));}void unionn(int x,int y){int Fa=find(x),Fb=find(y);if(x<y)fa[y]=x;else fa[x]=y;return;} }F; bool CmP(node x,node y) {return x.w<y.w;} bool cMp(node x,node y) {return x.id<y.id;} int main() {scanf("%d%d%d",&n,&m,&t);for(int i=1;i<=m;i++){scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].w);if(e[i].x>e[i].y)swap(e[i].x,e[i].y);lk[i]=mp(mp(e[i].x,e[i].y),i);e[i].id=i;}sort(lk+1,lk+1+m);for(int i=1;i<=t;i++){scanf("%d%d%d",&q[i].op,&q[i].x,&q[i].y);if(q[i].x>q[i].y)swap(q[i].x,q[i].y);if(q[i].op==2){q[i].x=(*lower_bound(lk+1,lk+1+m,mp(mp(q[i].x,q[i].y),0))).second;e[q[i].x].del=1; } }for(int i=1;i<=n+m;i++)from[i]=i,val[i]=w[i]=-inf;for(int i=1;i<=n;i++)F.fa[i]=i;for(int i=1;i<=m;i++)val[i+n]=w[i+n]=e[i].w;sort(e+1,e+1+m,CmP);for(int i=1;i<=m;i++){if(e[i].del)continue;int Fa=F.find(e[i].x),Fb=F.find(e[i].y);if(Fa==Fb)continue;F.unionn(Fa,Fb);LCT.Link(e[i].x,e[i].id+n);LCT.Link(e[i].id+n,e[i].y);}sort(e+1,e+1+m,cMp);for(int i=t;i>=1;i--){if(q[i].op==1){LCT.Split(q[i].x,q[i].y);ans[i]=w[q[i].y];}else{int id=q[i].x,x,y;y=e[id].y;x=e[id].x;LCT.Split(x,y);if(w[y]>e[id].w){int w=from[y];LCT.Cut(w,e[w-n].y);LCT.Cut(e[w-n].x,w);LCT.Link(x,id+n);LCT.Link(id+n,y);}}}for(int i=1;i<=t;i++)if(q[i].op==1)printf("%d\n",ans[i]);return 0; } 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的P4172-[WC2006]水管局长【LCT,最小生成树】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: iShot,MacBook电脑最好用的截
- 下一篇: 怎样远程控制手机手机如何远程遥控电脑