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 }
View Code

 

posted @ 2017-10-19 22:51  bin_gege  阅读(379)  评论(0编辑  收藏  举报