您的位置:首页 > 其它

【lct】bzoj2049 [Sdoi2008]Cave 洞穴勘测

2017-10-10 22:52 375 查看
题意:维护一个动态并查集,支持加边,删边,维护两点连通性。

主要用到了 lct 的 Access FindRoot ChangeRoot link cut 操作。

#include<cstdio>
#include<iostream>
#include<stack>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 10005
int fa[maxn],c[maxn][2],siz[maxn];
bool is_root[maxn],delta[maxn];
void Mark(int x){
if(x){
delta[x]^=1;
}
}
void Maintain(int x)
{
siz[x]=siz[c[x][0]]+siz[c[x][1]]+1;
}
void pushdown(int x){
if(delta[x]){
Mark(c[x][0]);
Mark(c[x][1]);
swap(c[x][0],c[x][1]);
delta[x]=0;
}
}
void Rotate(int x,bool flag)
{
int y=fa[x];
c[y][!flag]=c[x][flag];
if(c[x][flag]){
fa[c[x][flag]]=y;
}
if(fa[y] && c[fa[y]][c[fa[y]][1]==y]==y){
c[fa[y]][c[fa[y]][1]==y]=x;
}
fa[x]=fa[y];
c[x][flag]=y;
fa[y]=x;
if(is_root[y]){
is_root[y]=0;
is_root[x]=1;
}
Maintain(y);
Maintain(x);
}
stack<int>st;
void Splay(int x)
{
pushdown(x);
if(!x || is_root[x]){
return;
}
int U=x;
while(!is_root[U]){
st.push(U);
U=fa[U];
}
st.push(U);
while(!st.empty()){
pushdown(st.top());
st.pop();
}
int y;
while(y=fa[x],(!is_root[x])){
if(is_root[y]){
Rotate(x,c[y][0]==x);
}
else{
if((c[y][0]==x)==(c[fa[y]][0]==y)){
Rotate(y,c[fa[y]][0]==y);
}
else{
Rotate(x,c[y][0]==x);
y=fa[x];
}
Rotate(x,c[y][0]==x);
}
}
Maintain(x);
}
void Access(int x){
int y;
Splay(x);
while(fa[x]){
y=fa[x];
Splay(y);
Splay(x);
if(c[y][1]){
is_root[c[y][1]]=1;
}
is_root[x]=0;
c[y][1]=x;
Splay(x);
}
if(c[x][1]){
is_root[c[x][1]]=1;
c[x][1]=0;
}
}
void ChangeRoot(int x){
Access(x);
Splay(x);
Mark(x);
}
void cut(int x){
Access(x);
Splay(x);
fa[c[x][0]]=0;
if(c[x][0]){
is_root[c[x][0]]=1;
}
c[x][0]=0;
}
void link(int x,int y){
Access(x);
Splay(x);
//  Mark(c[x][0]);
Access(y);
Splay(y);
c[y][1]=x;
fa[x]=y;
is_root[x]=0;
}
int FindRoot(int x){
Access(x);
Splay(x);
while(c[x][0]){
x=c[x][0];
}
return x;
}
int n,m;
int main(){
//	freopen("bzoj2049.in","r",stdin);
char op[10];
int x,y;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i){
siz[i]=1;
is_root[i]=1;
}
for(int i=1;i<=m;++i){
scanf("%s%d%d",op,&x,&y);
if(op[0]=='Q'){
puts(FindRoot(x)==FindRoot(y) ? "Yes" : "No");
}
else if(op[0]=='C'){
ChangeRoot(x);
link(x,y);
}
else{
if(FindRoot(x)==FindRoot(y)){
ChangeRoot(x);
cut(y);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: