bzoj 2049: [Sdoi2008]Cave 洞穴勘测 link cut tree

来源:互联网 发布:犀牛软件 视角 加速器 编辑:程序博客网 时间:2024/05/20 13:18

题意:一开始有n个点,要求资瓷三个操作:

C u v表示u到v之间连一条边

D u v表示断开u到v之间的边(保证u到v之间一定有一条边)

Q u v表示询问u与v是否连通

保证任何时候都不会出现环


分析:之前对link cut tree这种神奇的数据结构并不是特别理解,没有理解到换根的时候要把splay进行旋转操作。

这题关键就是如何进行cut操作

我们可以先把x转到根节点,然后再把y进行access和splay操作,那么y的左儿子一定是x


代码:

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<stack>#define N 10005using namespace std;int n,m;stack <int> q;struct tree{int l,r,fa,rev;}t[N];void rttl(int x){int y=t[x].r;t[x].r=t[y].l;t[t[y].l].fa=x;if (x==t[t[x].fa].l) t[t[x].fa].l=y;else if (x==t[t[x].fa].r) t[t[x].fa].r=y;t[y].fa=t[x].fa;t[y].l=x;t[x].fa=y;}void rttr(int x){int y=t[x].l;t[x].l=t[y].r;t[t[y].r].fa=x;if (x==t[t[x].fa].l) t[t[x].fa].l=y;else if (x==t[t[x].fa].r) t[t[x].fa].r=y;t[y].fa=t[x].fa;t[y].r=x;t[x].fa=y;}bool isroot(int x){if (x!=t[t[x].fa].l&&x!=t[t[x].fa].r||!t[x].fa) return 1;return 0;}void pushdown(int x){if (t[x].rev){swap(t[x].l,t[x].r);if (t[x].l) t[t[x].l].rev^=1;if (t[x].r) t[t[x].r].rev^=1;t[x].rev^=1;}}void remove(int x){int y=x;while (1){q.push(y);if (isroot(y)) break;y=t[y].fa;}while (!q.empty()){int y=q.top();q.pop();pushdown(y);}}void splay(int x){remove(x);while (!isroot(x)){int p=t[x].fa,g=t[p].fa;if (isroot(p)){if (x==t[p].l) rttr(p);else rttl(p);break;}if (x==t[p].l){if (p==t[g].l){rttr(g);rttr(p);}else{rttr(p);rttl(g);}}else{if (p==t[g].r){rttl(g);rttl(p);}else{rttl(p);rttr(g);}}}}void access(int x){int y=0;while (x){splay(x);t[x].r=y;y=x;x=t[x].fa;}}void movetoroot(int x){access(x);splay(x);t[x].rev^=1;}void cut(int x,int y){movetoroot(x);access(y);splay(y);t[y].l=0;t[x].fa=0;}void link(int x,int y){movetoroot(x);access(y);t[y].r=x;t[x].fa=y;splay(x);}int findroot(int x){access(x);splay(x);while (t[x].l) x=t[x].l;return x;}int main(){scanf("%d%d",&n,&m);for (int i=1;i<=m;i++){char ch[10];int x,y;scanf("%s%d%d",ch,&x,&y);if (ch[0]=='C') link(x,y);else if (ch[0]=='D') cut(x,y);else if (findroot(x)==findroot(y)) printf("Yes\n");else printf("No\n");}return 0;}


0 0