Codeforces987F

题目链接:

http://codeforces.com/contest/987/problem/F

F. 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 m

with integer elements between 0 and 2n1 inclusive. Let's build an undirected graph on these integers in the following way: connect two integers x and y with an edge if and only if x&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 n

and m ( 0n22, 1m2n

).

In the second line there are m

integers a1,a2,,am ( 0ai<2n) — the elements of the set. All ai

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:

扫描二维码关注公众号,回复: 2239800 查看本文章

Graph from second sample:


题意:给你一个n,一个m,m < 2^n, 然后就是如果 x & y == 0 的话就可以将这2个数连起来, 求最后的有几块。

题解: 不难想到,x有边连出的一定是 (2^n-1) ^ x 的一个子集,直接连子集复杂度是爆炸的。。。但是我们可以一个1一个1的消去,最后变成补集的一个子集。

但是必须当且仅当 至少有一个 a 等于 x 的时候, 可以直接dfs(all ^ x) ,否则直接消1连边。。。

#include <bits/stdc++.h>

using namespace std;
const int maxn = 1<<22;

int n, m, a[maxn], all;
int vis[maxn];
int have[maxn];

void dfs(int x)
{
    if(vis[x]) return;
    vis[x] = 1;
    if(have[x]) dfs(all ^ x);
    for(int i = 0;i < n;i ++) {
        if(x & 1 << i) dfs(x ^ 1 << i);
    }
}
int main()
{
    ios::sync_with_stdio(false), cin.tie(0);
    cin >> n >> m;
    for(int i = 1;i <= m;i ++) cin >> a[i];
    for(int i = 1;i <= m;i ++) have[a[i]] = 1;
    all = 1<<n;
    all--;
    int res = 0;
    for(int i = 1;i <= m;i ++) {
        if(!vis[a[i]]) {
            vis[a[i]] = 1;
            res ++;
            dfs(all ^ a[i]);
        }
    }
    cout << res << '\n';
    return 0;
}


猜你喜欢

转载自blog.csdn.net/qq_36876305/article/details/80531887