连接两个点,断开两个点,询问两个点是否联通。
lct第一道,
基本的access函数,move_to_rt函数,link函数都在里面了,但是cut函数还不是特别理解。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<stack>
using namespace std;
inline int read()
{
int ans,f=1;char ch;
while ((ch=getchar())<'0'||ch>'9') if (ch=='-') f=-1;ans=ch-'0';
while ((ch=getchar())>='0'&&ch<='9')ans=ans*10+ch-'0';
return ans*f;
}
int n,m;
int fa[10005],ch[10005][2];
bool rev[10005];
inline bool isroot(int u)
{
return ch[fa[u]][0]!=u && ch[fa[u]][1]!=u;
}
void down(int u)
{
int l=ch[u][0],r=ch[u][1];
if (rev[u])
{
rev[l]^=1;rev[r]^=1;rev[u]^=1;
swap(ch[u][1],ch[u][0]);
}
}
void rot(int x)
{
int y=fa[x],z=fa[y],l,r;
if (ch[y][0]==x) l=0;else l=1;r=l^1;
if (!isroot(y))
if (ch[z][0]==y) ch[z][0]=x;else ch[z][1]=x;
fa[y]=x;fa[ch[x][r]]=y;fa[x]=z;
ch[y][l]=ch[x][r];ch[x][r]=y;
}
void splay(int x)
{
stack<int> s;
int y=x,z;
while (!isroot(y)) s.push(y),y=fa[y];s.push(y);
while (!s.empty()) down(s.top()),s.pop();
while (!isroot(x))
{
y=fa[x],z=fa[y];
if (!isroot(y))
if (ch[z][0]==y^ch[y][0]==x) rot(x);else rot(y);
rot(x);
}
}
void access(int u)
{
int t=0;
while (u)
{
splay(u);
ch[u][1]=t;
t=u;u=fa[u];
}
}
void to_rt(int u)
{
access(u);splay(u);rev[u]^=1;
}
void link(int u,int v)
{
to_rt(u);fa[u]=v;splay(u);
}
void cut(int u,int v)
{
to_rt(u);access(v);splay(v);ch[v][0]=fa[u]=0;
}
int find(int u)
{
access(u);splay(u);
while (ch[u][0]) u=ch[u][0];
return u;
}
int main()
{
n=read();m=read();
char s[10];
int x,y;
while (m--)
{
scanf("%s",s);
x=read(),y=read();
if (s[0]=='C') link(x,y);
else if (s[0]=='D') cut(x,y);
else
{
if (find(x)==find(y)) printf("Yes\n");else printf("No\n");
}
}
return 0;
}
总结
1:lct的各种操作还是要不断积累,以此来使自己的理解更加深入透彻。毕竟还是要多思考才能有新的发现。