# [ BZOJ 4668 ] 冷战

$\\$

## $Description$

$N$个点，开始没有边相连，进行按顺序给出的$M$个操作：

• $0\ u\ v$$u,v$两点连一条边
• $1\ u\ v$ 查询$u,v$两点最早在第几条边连接的时候被连通

• $N,M\in [1,5\times 10^5]$

$\\$

## $Solution$

$\\$

## $Code$

#include<cmath>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 500010
#define R register
#define gc getchar
using namespace std;

int n,m,ans,cnt;

struct UFS{
int f[N],g[N],d[N],sz[N];

UFS(){for(R int i=1;i<N;++i)f[i]=i,d[i]=sz[i]=1;}

int find(int x){
if(x==f[x])return x;
int ans=find(f[x]); d[x]=d[f[x]]+1; return ans;
}

inline void merge(int x,int y){
int fx=find(x),fy=find(y);
if(sz[fx]>sz[fy]) fx^=fy^=fx^=fy;
sz[fy]+=sz[fx]; f[fx]=fy; g[fx]=cnt; d[fx]=d[fy]+1;
}

inline int lca(int x,int y){
int ans=0;
if(d[x]>d[y]) x^=y^=x^=y;
while(d[y]>d[x]) ans=max(ans,g[y]),y=f[y];
if(x==y) return ans;
while(x!=y){
ans=max(ans,max(g[x],g[y]));
x=f[x]; y=f[y];
}
return ans;
}

}ufs;

inline int rd(){
int x=0; bool f=0; char c=gc();
while(!isdigit(c)){if(c=='-')f=1;c=gc();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
return f?-x:x;
}

int main(){
n=rd(); m=rd();
for(R int i=1,op,x,y;i<=m;++i){
op=rd(); x=rd()^ans; y=rd()^ans;
if(op==0){
++cnt;
if(ufs.find(x)!=ufs.find(y)) ufs.merge(x,y);
}
else if(ufs.find(x)!=ufs.find(y)){ans=0;puts("0");}
else printf("%d\n",(ans=ufs.lca(x,y)));
}
return 0;
}

posted @ 2018-10-06 19:00  SGCollin  阅读(167)  评论(0编辑  收藏  举报