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; }