# bzoj2049Cave 洞穴勘测

Description

Input

Output

Sample Input

200 5
Query 123 127
Connect 123 127
Query 123 127
Destroy 127 123
Query 123 127

3 5
Connect 1 2
Connect 3 1
Query 2 3
Destroy 1 3
Query 2 3

Sample Output

No
Yes
No

Yes
No

“每条通道连接了恰好两个洞穴”,”无论通道怎么改变，任意时刻任意两个洞穴之间至多只有一条路径”

1.连边
2.拆边
3.查询两个点是不是联通

#include<cstdio>
#include<cstring>
#include<iostream>

using namespace std;

const int N=10010;
int n,m,ch[N][2],pre[N],q[N];
bool rev[N];

int get(int bh)
{
return (ch[pre[bh]][0]==bh ? 0:1);
}

void push(int bh)
{
if (rev[bh])
{
rev[bh]^=1;
rev[ch[bh][0]]^=1; rev[ch[bh][1]]^=1;
swap(ch[bh][0],ch[bh][1]);
}
}

bool isroot(int bh)
{
return ch[pre[bh]][1]!=bh&&ch[pre[bh]][0]!=bh;
}

void rotate(int bh)
{
int fa=pre[bh];
int grand=pre[fa];
int wh=get(bh);
if (!isroot(fa)) ch[grand][ch[grand][0]==fa ? 0:1]=bh;  //
ch[fa][wh]=ch[bh][wh^1];
pre[ch[fa][wh]]=fa;
ch[bh][wh^1]=fa;
pre[fa]=bh;
pre[bh]=grand;
return;
}

void splay(int bh)
{
int top=0;
q[++top]=bh;
for (int i=bh;!isroot(i);i=pre[i])   //!isroot(i);i=pre[i]
q[++top]=pre[i];
while (top)
push(q[top--]);
for (int fa;!isroot(bh);rotate(bh))
if (!isroot(fa=pre[bh]))
rotate(get(fa)==get(bh) ? fa:bh);
return;
}

void expose(int bh)  //查询x
{
int t=0;
while (bh)
{
splay(bh);
ch[bh][1]=t;  //
t=bh;
bh=pre[bh];
}
}

void makeroot(int bh)  //翻转操作
{
expose(bh);
splay(bh);
rev[bh]^=1;
}

{
makeroot(x);
pre[x]=y;   //
splay(x);
}

void cut(int x,int y)
{
makeroot(x);
expose(y);
splay(y);
ch[y][0]=pre[x]=0;  //ch[y][0]=pre[x]
}

int find(int bh)  //寻找x所在的辅助树中对应的原树的根（深度最小）
{
expose(bh);
splay(bh);
int t=bh;
while (ch[t][0]) t=ch[t][0];
return t;
}

int main()
{
scanf("%d%d",&n,&m);
char opt[10];
scanf("%c",&opt[0]);
for (int i=1;i<=m;i++)
{
int x,y;
scanf("%s",&opt);
scanf("%d%d",&x,&y);