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个点,每个点都不同且每个点权值小于2^n,现在每两个点权值AND操作后等于0的连一条边,问操作过后,图中连通块的个数。
思路:对于每个点dfs,将包含它的所有数字都加入到集合中。。。
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std;
typedef long long ll;
const int maxn = (1<<22);
ll a[maxn];
ll b[maxn];
bool vis[maxn];
int tot;
void dfs(int x)
{
vis[x] = 1;
//所有父节点都dfs
for(int i=0;i<22;i++)
{
if((x&(1<<i))==0&&!vis[x|(1<<i)])
{
dfs(x|(1<<i));
}
}
//对于图中有的与x可以相连的点(此时还未处理),dfs,之后就不用为它单独dfs
if(b[tot^x]&&!vis[tot^x])
{
dfs(tot^x);
}
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
tot = (1<<n)-1;
memset(vis,0,sizeof(vis));
for(int i=1;i<=m;i++)
{
scanf("%d",&a[i]);
b[a[i]]=1;
}
int cnt=0;
for(int i=1;i<=m;i++)
{
//a[i]无法与现有点连边,连通块数++
if(!vis[tot^a[i]])
{
cnt++;
//a[i]没有冲突点则dfs
if(!vis[a[i]])
{
dfs(a[i]);
}
}
}
printf("%d\n",cnt);
}
}