C. AND Graph
time limit per test
4 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
You are given a set of size mm with integer elements between 00 and 2n−12n−1 inclusive. Let's build an undirected graph on these integers in the following way: connect two integers xx and yy with an edge if and only if x&y=0x&y=0. Here && is the bitwise AND operation. Count the number of connected components in that graph.
Input
In the first line of input there are two integers nn and mm (0≤n≤220≤n≤22, 1≤m≤2n1≤m≤2n).
In the second line there are mm integers a1,a2,…,ama1,a2,…,am (0≤ai<2n0≤ai<2n) — the elements of the set. All aiai are distinct.
Output
Print the number of connected components.
Examples
input
Copy
2 3 1 2 3
output
Copy
2
input
Copy
5 5 5 19 10 20 12
output
Copy
2
Note
Graph from first sample:
Graph from second sample:
思路:
如果我们暴力搜索m个数的话,明显会超时,所以我们考虑,如果x&y=0 ,
那么二进制下,假设x为10101,那么y就为01010(x对应位取反)的一个”子集”,
此处子集意为y中的某些1变为0,比如此时y的子集有(01010,01000,00001,00000)。
所以对于y我们找到它所有的子集,如果某个y的子集u在a数组中,那么我们就可以把u
看作新的x再进行这种操作。
怎么找y的所有子集呢,我们一个1一个1的消去即可,DFS每层消一个1。
对于一个x怎么找到y呢,我们让x ^ ((1<<n) - 1)) 即可。
对于y怎么找到某一个1并将其消去呢,y&(1<<i)可以判断出来第i位是否
为1,y^(1<<i)可以使得第i位的1变为0,其他位置不变。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=(1<<22)+5;
bool is[maxn],vis[maxn];
int n,m,S,a[maxn];
void dfs(int x)
{
if(vis[x])return;
vis[x]=1;
if(is[x])dfs(x^S);
for(int i=0;i<n;i++)
if(x>>i&1)
dfs(x^(1<<i));
}
int main()
{
scanf("%d%d",&n,&m);
S=(1<<n)-1;
for(int i=0;i<m;i++)
{
scanf("%d",&a[i]);
is[a[i]]=1;
}
int ans=0;
for(int i=0;i<m;i++)
{
if(!vis[a[i]])
{
ans++;vis[a[i]]=1;
dfs(a[i]^S);
}
}
printf("%d\n",ans);
return 0;
}