博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
牛客练习赛39 D:动态连通块(并查集+bitset优化)
阅读量:3898 次
发布时间:2019-05-23

本文共 1174 字,大约阅读时间需要 3 分钟。

【题目】

【题解】

题意:连通块的意思是颜色相同且互相之间可以连通的点集。操作有三种: 1、在两个点之间连一条边。2、询问白(黑)连通块个数。3、给出x,y两个相同颜色的点,询问存在多少个异色的点,将它改变颜色后,x,y所在的连通块会合并为一个。如果x,y已经在一个连通块内了,输出-1。

思路:用并查集判断连一条边是不是要合并连通块,用bitset维护每个白联通块连出的黑点,黑连通块连出的白点,暴力跑一遍就好了。

复杂度图片说明 ,W=32或64。

【代码】

#include 
using namespace std;const int maxn=50005;bitset
f[maxn],g;int pre[maxn],col[maxn];int ans[2]={0}; //连通块个数计数int Find(int x){ return x==pre[x]? x : pre[x]=Find(pre[x]);}void add(int u,int v) //在两个点之间连一条边{ int a=Find(u),b=Find(v); if(col[u]==col[v]) { if(a!=b) { pre[a]=b; f[b]|=f[a]; //取a b并集给b ans[col[a]]--; } } else f[a].set(v),f[b].set(u);}void query(int u,int v){ u=Find(u),v=Find(v); if(u==v) { puts("-1"); return ; } g=f[u]&f[v]; //取a b交集给g printf("%d\n",g.count());}int main(){ int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&col[i]); pre[i]=i; ans[col[i]]++; } while(m--) { int opt,a,b; scanf("%d%d",&opt,&a); if(opt==1) scanf("%d",&b),add(a,b); else if(opt==2) printf("%d\n",ans[a]); else if(opt==3) scanf("%d",&b),query(a,b); } return 0;}

 

转载地址:http://ybben.baihongyu.com/

你可能感兴趣的文章
用C#通过888-TT打印中文标签
查看>>
sendmail 出现 My unqualified host name的解决办法
查看>>
彻底解决lazarus安装组件后烦人的编译时单元找不到的问题!
查看>>
Delphi的参数修饰const/var/output 与C++的对应关系
查看>>
C++ free与delete区别
查看>>
VC的字符串转换atlconv的使用
查看>>
Twitter的分布式自增ID算法snowflake (Java版)
查看>>
CentOS7 安装配置FastDFS
查看>>
递归算法的时间复杂度
查看>>
数据结构之图(存储结构、遍历)
查看>>
使用sizeof计算类的大小
查看>>
乐观锁与悲观锁——解决并发问题
查看>>
operator 类型转换及重载
查看>>
HTTP状态码
查看>>
TCP/IP详解--举例明白发送/接收缓冲区、滑动窗口协议之间的关系
查看>>
TCP/IP详解--再次深入理解TCP网络编程中的send和recv
查看>>
TCP与UDP收发的时候TCP有缓冲区还是UDP有缓冲区,使用它们时该注意什么?
查看>>
C++中map、hash_map、unordered_map、unordered_set通俗辨析
查看>>
clone的fork与pthread_create创建线程有何不同&pthread多线程编程的学习小结
查看>>
运算符重载参数的顺序对运算是否有影响
查看>>