hdu 5967 小R与手机(LCT裸题)
题目链接:hdu 5967 小R与手机
题意:
有n个手机,每个手机有一个呼叫转移。如果形成了环就不能接通。
现在有两个操作:
1 询问打电话x,最终接到的是那个电话,如果有环,输出-1
2 将x的呼叫转移改为y
题解:
用LCT来维护这个森林的关系。
显然要形成环的话,肯定是树跟连向了该树内的点。
所以特别维护一下树根的连向就行了。
1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;i++) 3 #define mst(a,b) memset(a,b,sizeof(a)) 4 using namespace std; 5 6 namespace LCT 7 { 8 const int N=2e5+7; 9 int f[N],son[N][2],tmp[N];bool rev[N]; 10 bool isroot(int x){return !f[x]||son[f[x]][0]!=x&&son[f[x]][1]!=x;} 11 void rotate(int x){ 12 int y=f[x],w=son[y][1]==x; 13 son[y][w]=son[x][w^1]; 14 if(son[x][w^1])f[son[x][w^1]]=y; 15 if(f[y]){ 16 int z=f[y]; 17 if(son[z][0]==y)son[z][0]=x;else if(son[z][1]==y)son[z][1]=x; 18 } 19 f[x]=f[y];f[y]=x;son[x][w^1]=y; 20 } 21 void splay(int x){ 22 int s=1,i=x,y;tmp[1]=i; 23 while(!isroot(x)){ 24 y=f[x]; 25 if(!isroot(y)){if((son[f[y]][0]==y)^(son[y][0]==x))rotate(x);else rotate(y);} 26 rotate(x); 27 } 28 } 29 void access(int x){for(int y=0;x;y=x,x=f[x])splay(x),son[x][1]=y;} 30 int root(int x){access(x);splay(x);while(son[x][0])x=son[x][0];return x;} 31 void makeroot(int x){access(x);splay(x);} 32 void link(int x,int y){makeroot(x);f[x]=y;access(x);} 33 void cutf(int x){access(x);splay(x);f[son[x][0]]=0;son[x][0]=0;} 34 void cut(int x,int y){makeroot(x);cutf(y);} 35 } 36 37 using namespace LCT; 38 int n,m,x,y,op,fa[N],a[N]; 39 40 void Link(int x,int y) 41 { 42 int rt=root(x); 43 if(rt==x)fa[x]=0;else cutf(x); 44 if(fa[rt]&&root(fa[rt])!=rt) 45 link(rt,fa[rt]),fa[rt]=0; 46 if(!y)return; 47 if(root(y)==x)fa[x]=y;else link(x,y); 48 } 49 50 int main() 51 { 52 scanf("%d%d",&n,&m); 53 F(i,1,n) 54 { 55 scanf("%d",a+i); 56 if(a[i])Link(i,a[i]); 57 } 58 F(i,1,m) 59 { 60 scanf("%d",&op); 61 if(op==1)scanf("%d%d",&x,&y),Link(x,y); 62 else 63 { 64 scanf("%d",&x); 65 int rt=root(x); 66 if(fa[rt])puts("-1"); 67 else printf("%d\n",rt); 68 } 69 } 70 return 0; 71 }