BZOJ4998 星球联盟
题目描述
题目分析
发现题目说白了就是让你动态维护强连通分量。决定使用lct来维护,外面套一个并查集来维护连通性,查的时候直接输出当前集合的大小就可以了。
是代码呢
#include <bits/stdc++.h>
using namespace std;
const int MAXN=2e5+7;
#define lc ch[x][0]
#define rc ch[x][1]
int q[MAXN],s[MAXN],size[MAXN],n,m,r[MAXN],st[MAXN],ch[MAXN][2],fa[MAXN],f[MAXN],Q,add[MAXN];
inline int find(int x){return fa[x]==x?fa[x]:fa[x]=find(fa[x]);}
inline bool nroot(int x){return ch[f[x]][0]==x||ch[f[x]][1]==x;}
inline void pushr(int x){swap(lc,rc);r[x]^=1;}
inline void pushup(int x){s[x]=s[lc]+s[rc]+add[x];}
inline void pushdown(int x)
{
if(r[x]){
if(lc) pushr(lc);
if(rc) pushr(rc);
r[x]=0;
}
}
inline void rotate(int x)
{
int y=f[x],z=f[y],kind=ch[y][1]==x,w=ch[x][!kind];
if(nroot(y)) ch[z][ch[z][1]==y]=x;ch[x][!kind]=y;ch[y][kind]=w;
if(w) f[w]=y;f[y]=x;f[x]=z;
pushup(y);
}
inline void splay(int x)
{
int y=x,z=0;
st[++z]=y;
while(nroot(y)) st[++z]=y=f[y];
while(z) pushdown(st[z--]);
while(nroot(x)){
y=f[x];z=f[y];
if(nroot(y)) rotate((ch[y][0]==x)^(ch[z][0]==y)?y:x);
rotate(x);
}
pushup(x);
}
inline void access(int x)
{
for(int y=0;x;y=x,x=f[y]=find(f[x]))
splay(x),rc=y,pushup(x);
}
inline void makeroot(int x)
{
access(x);splay(x);pushr(x);
}
inline int findroot(int x)
{
access(x);splay(x);
while(lc) pushdown(x),x=lc;
splay(x);
return x;
}
inline void split(int x,int y)
{
makeroot(x);access(y);splay(y);
}
inline void merge(int x,int y)
{
if(x==y) return;
makeroot(x);
if(findroot(y)!=x){
f[x]=y;
return;
}
makeroot(y);access(x);splay(x);
int cnt=s[x];
int L=0,R=0;
q[++R]=x;
while(L<R){
x=q[++L];
if(lc) q[++R]=lc;
if(rc) q[++R]=rc;
fa[x]=y;
add[x]=s[x]=f[x]=lc=rc=0;
}
add[y]=s[y]=cnt;
f[y]=0;
}
inline int read()
{
int x=0,c=1;
char ch=' ';
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
while(ch=='-')c*=-1,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*c;
}
int main()
{
n=read();m=read();Q=read();
for(int i=1;i<=n;i++){
add[i]=s[i]=1;fa[i]=i;
}
for(int i=1;i<=m;i++){
int x=read(),y=read();
x=find(x),y=find(y);
merge(x,y);
}
for(int i=1;i<=Q;i++){
int x=read(),y=read();
x=find(x);y=find(y);
if(x==y){
printf("%d\n",add[x]);
continue;
}
makeroot(x);
if(findroot(y)!=x){
f[x]=y;
puts("No");
continue;
}
makeroot(y);access(x);splay(x);
int cnt=s[x];
int L=0,R=0;
q[++R]=x;
while(L<R){
x=q[++L];
if(lc) q[++R]=lc;
if(rc) q[++R]=rc;
fa[x]=y;
add[x]=s[x]=f[x]=lc=rc=0;
}
add[y]=s[y]=cnt;f[y]=0;
printf("%d\n",add[y]);
}
return 0;
}