题意:
白连通块:图中一个点集V,若满足所有点都是白点,并且V中任意两点都可以只经过V中的点互相到达,
则称V中的点构成了一个白连通块。
黑连通块:类似白连通块的定义。
给你n个点,每一个点有白(0)/黑(1)。
然后有m个操作。
操作1:在u,v之间连一条边
操作2:输出颜色为白(0)/黑(1)连通块的个数
操作3:x,y两个点,保证是同色。假定是白色,那么如果x,y在一个连通块里,就输出-1,否则,问你只改变一个黑点的颜色,使得这两个连通块的变成一个连通块,问你这样的黑点有多少个
解析:
这道题题意操作3读不懂,所以直接看题解了...很简单,就用并查集维护连通块,并且同bitset,记录每一个白/黑连通块连接的黑/白点。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <bitset>
using namespace std;
const int N = 5e4+10;
bitset<N> vis[N];
int col[N];
int fa[N];
int ku[2];
int findfa(int x)
{
if(x==fa[x]) return x;
int nex=fa[x];
fa[x]=findfa(nex);
return fa[x];
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&col[i]);fa[i]=i;
ku[col[i]]++;
}
for(int i=1;i<=m;i++)
{
int id,u,v;
scanf("%d%d",&id,&u);
if(id==1)
{
scanf("%d",&v);
if(col[u]==col[v])//
{
int fx=findfa(u);
int fy=findfa(v);
if(fx!=fy)
{
fa[fx]=fy;
vis[fy]|=vis[fx];
ku[col[u]]--;
}
}
else
{
vis[findfa(u)].set(v);
vis[findfa(v)].set(u);
}
}
else if(id==2)
{
printf("%d\n",ku[u]);
}
else
{
scanf("%d",&v);
int fx=findfa(u);
int fy=findfa(v);
if(fx==fy) printf("-1\n");
else
{
bitset<N> tmp=vis[fx]&vis[fy];
printf("%d\n",tmp.count());
}
}
}
}