[BZOJ4668]冷战
题目大意:
一个$n(n\le5\times10^5)$个点的图,初始时没有边,有$m(m\le5\times10^5)$次操作,操作包含以下两种:
1.在$u,v$之间连一条无向边;
2.询问$u,v$经过几次操作1之后连通。
思路:
并查集按秩合并,不路径压缩。询问时暴力LCA求路径最大值。时间复杂度$O(m\log n)$。
1 #include<cstdio> 2 #include<cctype> 3 #include<algorithm> 4 inline int getint() { 5 register char ch; 6 while(!isdigit(ch=getchar())); 7 register int x=ch^'0'; 8 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 9 return x; 10 }; 11 const int N=500001; 12 int par[N],w[N],h[N],dep[N]; 13 int find(const int &x) { 14 if(par[x]==x) return x; 15 const int ret=find(par[x]); 16 dep[x]=dep[par[x]]+1; 17 return ret; 18 } 19 inline int query(int u,int v) { 20 int ret=0; 21 while(u!=v) { 22 if(dep[u]<dep[v]) std::swap(u,v); 23 ret=std::max(ret,w[u]); 24 u=par[u]; 25 } 26 return ret; 27 } 28 int main() { 29 const int n=getint(); 30 for(register int i=1;i<=n;i++) h[par[i]=i]=1; 31 for(register int m=getint(),ans=0,cnt=0;m;m--) { 32 const int opt=getint(),u=getint()^ans,v=getint()^ans; 33 if(opt==0) { 34 int x=find(u),y=find(v); 35 if(h[x]>h[y]) std::swap(x,y); 36 h[par[x]=y]=std::max(h[y],h[x]+1); 37 w[x]=++cnt; 38 } 39 if(opt==1) printf("%d\n",ans=find(u)!=find(v)?0:query(u,v)); 40 } 41 return 0; 42 }