Codeforces Round #485 (Div. 2) - F - AND Graph

匿名 (未验证) 提交于 2019-12-03 00:22:01

传送门:点击打开链接

题意:给n和m,还有m个互不相同的数,均小于1<<n,如果m个数字中a & b = 0,那么a 和b有边相连,问有多少个连通分量。

分析:把每个数看做一个01集合,对于在m个数中的数,求它的补集的子集个数即可这里用4位来举个例子,比如5(0101),补集:(1010),补集的子集:(1010)  (1000) (0010) (0000)补集的子集和该集合的&运算的结果为0,满足条件。那么就可以枚举0 - ((1<<n) - 1)进行DFS即可。每次找到所有联通的点。时间复杂度O(1<<n)。注意反码和按位取反的区别。反码不需要对符号位取反,按位取反是对所有位取反。计算机内部在做数学运算时(也就是计算机的0和1的运算),都是以补码为标准的,说白了 计算机中就一种码那就是补码,而现实社会中的编码规则,例如原码、反码都是我们自定义的,为了和计算机中的补码形成转换关系。

代码:

#include<bits/stdc++.h> using namespace std; int n,m,vis[1<<23],ct[1<<23];  void dfs(int x) {     if(vis[x]) return ;     vis[x]=1;     for(int i=0;i<n;i++)         if( x & (1<<i) )             dfs( x^(1<<i));     if(ct[x]) dfs( ((1<<n)-1) & (~x)); }  int main() {     cin>>n>>m;     for(int i=0;i<m;i++) {         int num;         cin>>num;         ct[num]=1;     }     int ans=0;     for(int i=0;i<(1<<n);i++)         if(ct[i] && !vis[i])             dfs( ((1<<n)-1) & (~i)),ans++;     cout<<ans<<endl; }

参考博客:https://www.cnblogs.com/fzl194/p/9112965.html

https://blog.csdn.net/coder__cs/article/details/79186677

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!