題目連接:hdu 5967 小R與手機php
題意:c++
有n個手機,每一個手機有一個呼叫轉移。若是造成了環就不能接通。ide
如今有兩個操做:spa
1 詢問打電話x,最終接到的是那個電話,若是有環,輸出-13d
2 將x的呼叫轉移改成ycode
題解:blog
用LCT來維護這個森林的關係。get
顯然要造成環的話,確定是樹跟連向了該樹內的點。it
因此特別維護一下樹根的連向就好了。event
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 }