n,m<=5e4;
首先操作2用并查集就行了。题解说的好啊!
考虑操作一,连的两个点如果同色,直接合并,然后这个颜色的联通块-1,然后合并bitset,就是或一下。bitset维护的是相连的异色结点。
如果两个点异色,那么我们就不管他们,直接在两个bitset里分别把对方设为1。
对于操作三 直接 (b[x]&b[y]).count(); 就行了。
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 5e4+5; 4 int fa[N]; 5 bitset<50001> b[N]; 6 int find(int a){ 7 return a==fa[a]?a:fa[a]=find(fa[a]); 8 } 9 int n,m,op,x,y,c[N]; 10 11 int main(){ 12 ios::sync_with_stdio(false); 13 cin>>n>>m; 14 int hei=0,bai; 15 for(int i=1;i<=n;i++){ 16 fa[i]=i;cin>>c[i]; 17 hei+=c[i]; 18 } 19 bai=n-hei; 20 while (m--){ 21 cin>>op; 22 if(op==1){ 23 cin>>x>>y; 24 int xx=x,yy=y; 25 x=find(x);y=find(y); 26 if(x==y)continue; 27 if(c[xx]==1){ 28 if(c[yy]==1)fa[y]=x,hei--,b[x]|=b[y]; 29 else b[x][yy]=1,b[y][xx]=1; 30 } else{ 31 if(c[yy]==0)fa[y]=x,bai--,b[x]|=b[y]; 32 else b[x][yy]=1,b[y][xx]=1; 33 } 34 } else if(op==2){ 35 cin>>x; 36 if(!x)cout<<bai<<endl; 37 else cout<<hei<<endl; 38 } else{ 39 cin>>x>>y; 40 x=find(x);y=find(y); 41 if(x==y)cout<<-1<<endl; 42 else{ 43 cout<<(b[x]&b[y]).count()<<endl; 44 } 45 } 46 } 47 }View Code