BZOJ2049 洞穴勘测(LCT)
【题目描述】
(太长也懒得复制了)
题目大意就是:给你N个点,这N个点一开始没有路径相连,然后给出M个操作,包含三个操作:
1.Query(x,y):询问x,y之间是否连通。
2.Connect(x,y):在x,y之间连一条边。
3.Destroy(x,y):将x,y之间的边删除。
最后对于每个Query,如果连通就输出"Yes",否则输出“No”。
【输入格式】
第一行为两个正整数n和m,分别表示洞穴的个数和终端机上出现过的指令的个数。以下m行,依次表示终端机上出现的各条指令。每行开头是一个表示指令种类的字符串s("Connect”、”Destroy”或者”Query”,区分大小写),之后有两个整数u和v (1≤u, v≤n且u≠v) 分别表示两个洞穴的编号。
【输出格式】
对每个Query指令,输出洞穴u和洞穴v是否互相连通:是输出”Yes”,否则输出”No”。(不含双引号)
【样例输入】
Connect 1 2
Connect 3 1
Query 2 3
Destroy 1 3
Query 2 3
【样例输出】
Yes
No
【备注】
10%的数据满足n≤1000, m≤20000
20%的数据满足n≤2000, m≤40000
30%的数据满足n≤3000, m≤60000
40%的数据满足n≤4000, m≤80000
50%的数据满足n≤5000, m≤100000
60%的数据满足n≤6000, m≤120000
70%的数据满足n≤7000, m≤140000
80%的数据满足n≤8000, m≤160000
90%的数据满足n≤9000, m≤180000
100%的数据满足n≤10000, m≤200000
保证所有Destroy指令将摧毁的是一条存在的通道
本题输入、输出规模比较大,建议c\c++选手使用scanf和printf进行I\O操作以免超时
【题目分析】
很裸的一道LCT题,命令只包含findroot、link、cut操作(但还是要把操作写完QAQ)
【代码~】
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e4+10;
int n,m,u,v,qr,que[MAXN];
struct node{
int fa,lc,rc;
int rev;
}tr[MAXN];
bool which(const int &x)
{
return tr[tr[x].fa].rc==x;
}
bool isroot(const int &x)
{
if(!tr[x].fa)
return true;
return tr[tr[x].fa].lc!=x&&tr[tr[x].fa].rc!=x;
}
void push_down(const int &root)
{
if(tr[root].rev)
{
swap(tr[root].lc,tr[root].rc);
if(tr[root].lc)
tr[tr[root].lc].rev^=1;
if(tr[root].rc)
tr[tr[root].rc].rev^=1;
tr[root].rev=0;
}
}
void rotate(const int &x)
{
int y=tr[x].fa,z=tr[y].fa,b=tr[y].lc==x?tr[x].rc:tr[x].lc;
if(z&&!isroot(y))
(tr[z].lc==y?tr[z].lc:tr[z].rc)=x;
tr[x].fa=z,tr[y].fa=x,b?tr[b].fa=y:0;
if(tr[y].lc==x)
tr[x].rc=y,tr[y].lc=b;
else
tr[x].lc=y,tr[y].rc=b;
}
void splay(const int &x)
{
que[qr=0]=x;
for(int y=x;!isroot(y);y=tr[y].fa)
que[++qr]=tr[y].fa;
for(int i=qr;i>=0;--i)
push_down(que[i]);
while(!isroot(x))
{
if(!isroot(tr[x].fa))
{
if(which(x)==which(tr[x].fa))
rotate(tr[x].fa);
else
rotate(x);
}
rotate(x);
}
}
void access(int x)
{
for(int y=0;x;y=x,x=tr[x].fa)
{
splay(x);
tr[x].rc=y;
if(y)
tr[y].fa=x;
}
}
int findroot(int x)
{
access(x);
splay(x);
while(push_down(x),tr[x].lc)
x=tr[x].lc;
splay(x);
return x;
}
void makeroot(int x)
{
access(x);
splay(x);
tr[x].rev=1;
}
void link(const int &x,const int &y)
{
makeroot(x);
tr[x].fa=y;
}
void cut(const int &x,const int &y)
{
makeroot(x);
access(y);
splay(y);
tr[y].lc=0;
tr[x].fa=0;
}
int Read()
{
int i=0,f=1;
char c;
for(c=getchar();(c>'9'||c<'0')&&c!='-';c=getchar());
if(c=='-')
f=-1,c=getchar();
for(;c>='0'&&c<='9';c=getchar())
i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
int main()
{
scanf("%d%d",&n,&m);
char ch;
for(int i=1;i<=m;++i)
{
while(ch=getchar(),ch>'Z'||ch<'A');
if(ch=='Q')
{
if(findroot(Read())==findroot(Read()))
printf("Yes\n");
else
printf("No\n");
}
else
{
if(ch=='C')
link(Read(),Read());
else
cut(Read(),Read());
}
}
return 0;
}