题意:给出n
(0≤n≤22)和m,和m个数ai,1 ≤ m ≤ 2n ,0≤ai<2n ,把ai & aj == 0 的连边,求最后有几个连通块
解析:一个一个去找肯定爆,那么就要转换一下思维,想一下什么样的数才能按位与ai为0
那么肯定是ai ^ ((1<<n)-1)的子集,所以去找它的所有子集即可
例1010 变成0101 子集有 0101 0100 0001
然后只有x是给出的那m个数种的时候 才能 ^ ,其他情况消1取子集
#include <bits/stdc++.h> #define mem(a, b) memset(a, b, sizeof(a)) using namespace std; const int maxn = (1<<22) + 5, INF = 0x7fffffff; int n, m, res; int a[maxn], vis[maxn], inc[maxn]; void dfs(int x) { if(vis[x]) return; vis[x] = 1; if(inc[x]) { dfs(x^((1<<n)-1)); } for(int i=0; i<n; i++) { if(x&(1<<i)) { int temp = x^(1<<i); if(!vis[temp]) { dfs(temp); } } } } int main() { mem(vis, 0); mem(inc, 0); scanf("%d%d", &n, &m); res = 0; for(int i=0; i<m; i++) { scanf("%d", &a[i]); inc[a[i]] = 1; } for(int i=0; i<m; i++) if(!vis[a[i]]) { vis[a[i]] = 1; res++; dfs(a[i]^((1<<n)-1)); } cout<< res <<endl; return 0; }