【洛谷3950】部落衝突(LCT維護連通性)
阿新 • • 發佈:2018-12-19
大致題意: 給你一棵樹,\(3\)種操作:連一條邊,刪一條邊,詢問兩點是否聯通。
\(LCT\)維護連通性
有一道類似的題目:【BZOJ2049】[SDOI2008] Cave 洞穴勘測。
這兩道題都是\(LCT\)動態維護連通性的模板題。
考慮將\(x\)和\(y\)連邊時,我們就在\(LCT\)上\(Link(x,y)\)。
同理,\(x\)和\(y\)斷邊時,就\(Cut(x,y)\)。
詢問連通性時,只要判斷\(FindRoot(x)\)與\(FindRoot(y)\)是否相等即可。
程式碼
#include<bits/stdc++.h> #define N 300000 #define swap(x,y) (x^=y^=x^=y) using namespace std; int n,u[N+5],v[N+5]; class Class_FIO { private: #define Fsize 100000 #define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,Fsize,stdin),A==B)?EOF:*A++) char ch,*A,*B,Fin[Fsize]; public: Class_FIO() {A=B=Fin;} inline void read(int &x) {x=0;while(!isdigit(ch=tc()));while(x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));} inline void readc(char &x) {while(isspace(x=tc()));} }F; class Class_LCT//LCT模板 { private: #define LCT_SIZE N #define Rever(x) (swap(node[x].Son[0],node[x].Son[1]),node[x].Rev^=1) #define PushDown(x) (node[x].Rev&&(Rever(node[x].Son[0]),Rever(node[x].Son[1]),node[x].Rev=0)) #define Which(x) (node[node[x].Father].Son[1]==x) #define Connect(x,y,d) (node[node[x].Father=y].Son[d]=x) #define IsRoot(x) (node[node[x].Father].Son[0]^x&&node[node[x].Father].Son[1]^x) #define MakeRoot(x) (Access(x),Splay(x),Rever(x)) int Stack[LCT_SIZE+5]; struct Tree { int Father,Rev,Son[2]; }node[LCT_SIZE+5]; inline void Rotate(int x) { register int fa=node[x].Father,pa=node[fa].Father,d=Which(x); !IsRoot(fa)&&(node[pa].Son[Which(fa)]=x),node[x].Father=pa,Connect(node[x].Son[d^1],fa,d),Connect(fa,x,d^1); } inline void Splay(int x) { register int fa=x,Top=0; while(Stack[++Top]=fa,!IsRoot(fa)) fa=node[fa].Father; while(Top) PushDown(Stack[Top]),--Top; while(!IsRoot(x)) fa=node[x].Father,!IsRoot(fa)&&(Rotate(Which(x)^Which(fa)?x:fa),0),Rotate(x); } inline void Access(int x) {for(register int son=0;x;x=node[son=x].Father) Splay(x),node[x].Son[1]=son;} inline int FindRoot(int x) {Access(x),Splay(x);while(node[x].Son[0]) PushDown(x),x=node[x].Son[0];return Splay(x),x;} public: inline void Link(int x,int y) {MakeRoot(x),FindRoot(y)^x&&(node[x].Father=y);} inline void Cut(int x,int y) {MakeRoot(x),!(FindRoot(y)^x)&&!(node[y].Father^x)&&!node[y].Son[0]&&(node[y].Father=node[x].Son[1]=0);} inline bool IsConnected(int x,int y) {return !(FindRoot(x)^FindRoot(y));}//判斷連通性 }LCT; int main() { register int query_tot,i,x,y,cnt=0;register char op; for(F.read(n),F.read(query_tot),i=1;i<n;++i) F.read(x),F.read(y),LCT.Link(x,y); while(query_tot--) { F.readc(op);switch(op) { case 'C':F.read(u[++cnt]),F.read(v[cnt]),LCT.Cut(u[cnt],v[cnt]);break;//連邊 case 'U':F.read(x),LCT.Link(u[x],v[x]);break;//刪邊 case 'Q':F.read(x),F.read(y),puts(LCT.IsConnected(x,y)?"Yes":"No");break;//詢問 } } return 0; }