题意:动态加边,求两点间割边和割点的个数。
我们可以用LCT来做:
对于割边,先是要以点代边,边权1,点权0,我们发现在一个环上的边全部都不是割边,所以如果添加的边的两个端点已经联通,我们就把路径上的全部点权值设置为0.
对于割点,我们动态维护圆方树,如果加一条边就会形成和环,那么就把环完全断掉,把环上的每一个点(方点和圆点)全部连在一个新的方点上。可以发现原来环上的任意两个点之间的距离都是2,所以能够保证时间复杂度。查询就输出圆点个数。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
template<typename T>inline void qr(T &x){
x=0;int f=0;char s=getchar();
while(s<'0'||'9'<s)f|=s=='-',s=getchar();
while('0'<=s&&s<='9')x=x*10+s-48,s=getchar();
x=f?-x:x;
}
const int mxn=4e5+10;
int tot1,tot2,num,sta[mxn],n,q,lastans;
struct LCT{
int d[mxn],fa[mxn],dat[mxn],ch[mxn][2];
bool rv[mxn],clr[mxn];
#define lc ch[x][0]
#define rc ch[x][1]
#define ls(x) ch[x][0]
#define rs(x) ch[x][1]
bool nrt(int x){return ls(fa[x])==x||rs(fa[x])==x;}
void crv(int x){
if(!x)return;
swap(lc,rc);rv[x]^=1;
}
void clear(int x){
if(!x)return;
d[x]=dat[x]=0;
clr[x]=1;
}
void pushdown(int x){
if(rv[x])
crv(lc),crv(rc),rv[x]=0;
if(clr[x])
clear(lc),clear(rc),clr[x]=0;
}
void update(int x){
dat[x]=dat[lc]+dat[rc]+d[x];
}
void rotate(int x){
int y=fa[x],z=fa[y],w=rs(y)==x;
if(nrt(y))ch[z][rs(z)==y]=x;fa[x]=z;
fa[ch[y][w]=ch[x][1-w]]=y;
ch[x][1-w]=y,fa[y]=x;
update(y);
}
void splay(int p){
int x=p,tp=0;
sta[++tp]=x;
while(nrt(x))sta[++tp]=x=fa[x];
while(tp)pushdown(sta[tp--]);x=p;
while(nrt(x)){
int y=fa[x],z=fa[y];
if(nrt(y))
(rs(z)==y)^(rs(y)==x)?rotate(x):rotate(y);
rotate(x);
}
update(x);
}
void access(int x){
for(int y=0;x;x=fa[y=x])
splay(x),rs(x)=y,update(x);
}
void makeroot(int x){
access(x),splay(x),crv(x);
}
int findroot(int x){
while(lc)pushdown(x),x=lc;
return x;
}
void dfs(int x){
sta[++num]=x;
if(lc){
dfs(lc);
fa[lc]=0,lc=0;
}
if(rc){
dfs(rc);
fa[rc]=0,rc=0;
}
}
void solve(int x,int y){
makeroot(x),access(y),splay(y);
if(findroot(y)!=x)puts("-1");
else printf("%d\n",lastans=(dat[ls(y)]+d[y]));
}
}t1,t2;
int main(){
// freopen("1.in","r",stdin);
// freopen("1.out","w",stdout);
qr(n),qr(q);tot1=tot2=n;
for(int i=1;i<=q;i++){
t1.d[n+i]=t1.dat[n+i]=1;
}
for(int i=1;i<=n;i++){
t2.d[i]=t2.dat[i]=1;
}
while(q--){
int op,x,y;qr(op),qr(x),qr(y);
x^=lastans;
y^=lastans;
if(op==1){
t1.makeroot(x);
t1.access(y);
t1.splay(y);
if(t1.findroot(y)!=x){
t1.fa[x]=++tot1;
t1.fa[tot1]=y;
}
else{
t1.clear(t1.ch[y][0]);
t1.update(y);
}
t2.makeroot(x);
t2.access(y);
t2.splay(y);
if(t2.findroot(y)!=x){
t2.fa[x]=++tot2;
t2.fa[tot2]=y;
}
else{
num=0;
t2.dfs(y);tot2++;
for(int i=1;i<=num;i++)t2.fa[sta[i]]=tot2;
}
}
else if(op==2)t1.solve(x,y);
else t2.solve(x,y);
}
return 0;
}