您的位置:首页 > 其它

[ LCT 并查集 ] BZOJ4998

2018-01-08 16:31 387 查看
长跑那题一样。将双联通分量用并查集缩起来就好了。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void Read(int& x){
char c=nc();
for(;c<'0'||c>'9';c=nc());
for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-48,c=nc());
}
const int N=200010;
int f
,F
,ch
[2],s
;
int k,n,m,q;
int x,y;
bool r
,b
;
int Find(int x){
return F[x]==x?x:F[x]=Find(F[x]);
}
inline bool Get(int x){
return ch[Find(f[x])][1]==x;
}
inline void Rotate(int x){
int y=Find(f[x]);bool d=Get(x);
if(b[y])b[x]=1,b[y]=0;else ch[Find(f[y])][Get(y)]=x;
ch[y][d]=ch[x][d^1];f[ch[y][d]]=y;
ch[x][d^1]=y;f[x]=f[y];f[y]=x;
}
inline void Update_rev(int x){
swap(ch[x][0],ch[x][1]);
r[x]^=1;
}
inline void Down(int x){
if(r[x])Update_rev(ch[x][0]),Update_rev(ch[x][1]),r[x]=0;
}
void P(int x){
if(!b[x])P(f[x]);
Down(x);
}
inline void Splay(int x){
for(P(x);!b[x];Rotate(x))
if(!b[Find(f[x])])Rotate(Get(x)==Get(F[f[x]])?F[f[x]]:x);
}
inline void Access(int x){
int y=0;
while(x){
Splay(x);
b[ch[x][1]]=1;ch[x][1]=y;b[y]=0;
y=x;x=Find(f[x]);
}
}
inline void mr(int x){
Access(x);Splay(x);Update_rev(x);
}
inline int find(int x){
if(f[x])return find(Find(f[x]));
return x;
}
inline void Link(int x,int y){
mr(x);f[x]=y;
}
void Merge(int x,int y){
if(!x)return;
Down(x);F[Find(x)]=y;
if(x!=y)s[y]+=s[x];
Merge(ch[x][0],y);Merge(ch[x][1],y);
ch[x][0]=ch[x][1]=0;
}
int main(){
Read(n);Read(m);Read(q);
for(int i=1;i<=n;i++)F[i]=i,b[i]=s[i]=1;
while(m--){
Read(x);Read(y);
x=Find(x);y=Find(y);
if(x==y)continue;
if(find(x)!=find(y))Link(x,y);else{
mr(x);Access(y);Splay(y);
Merge(y,y);
}
}
while(q--){
Read(x);Read(y);
x=Find(x);y=Find(y);
if(x==y){
printf("%d\n",s[x]);
continue;
}
if(find(x)!=find(y))Link(x,y),printf("No\n");else{
mr(x);Access(y);Splay(y);
Merge(y,y);
printf("%d\n",s[y]);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: