版权声明:随意转载哦......但还是请注明出处吧: https://blog.csdn.net/dreaming__ldx/article/details/81915488
传送门
可以发现需要维护连通性和两点连通时间。
前者显然是并查集的常规操作,关键就在于如何维护两点的连通时间。
然后会想到这个时候不能用路径压缩了,因为它会破坏原本树形集合的结构,因此可以启发式按size合并。
代码:
#include<bits/stdc++.h>
#define N 500005
using namespace std;
int n,m,fa[N],lastans=0,siz[N],f[N],dep[N],tim=0;
inline int read(){
int ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
inline void write(int x){
if(x>9)write(x/10);
putchar((x%10)^48);
}
inline int find(int x){
if(x==fa[x])return x;
int fx=find(fa[x]);
dep[x]=dep[fa[x]]+1;
return fx;
}
inline void merge(int x,int y){
int fx=find(x),fy=find(y);
if(fx==fy)return;
if(siz[fx]<siz[fy])fx^=fy,fy^=fx,fx^=fy;
siz[fx]+=siz[fy],f[fy]=tim,fa[fy]=fx;
}
inline int query(int x,int y){
int fx=find(x),fy=find(y);
if(fx^fy)return 0;
int ans=0;
while(x^y){
if(dep[x]<dep[y])x^=y,y^=x,x^=y;
ans=max(ans,f[x]);
x=fa[x];
}
return ans;
}
int main(){
n=read(),m=read();
for(int i=1;i<=n;++i)fa[i]=i,siz[i]=1;
while(m--){
int op=read(),x=lastans^read(),y=lastans^read();
if(!op)++tim,merge(x,y);
else write((lastans=query(x,y))),puts("");
}
return 0;
}