CodeForce 986 C. AND Graph(dfs+位运算)

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 2n12n−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 (0n220≤n≤221m2n1≤m≤2n).

In the second line there are mm integers a1,a2,,ama1,a2,…,am (0ai<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;
}

猜你喜欢

转载自blog.csdn.net/albertluf/article/details/80722694