题解
O(m*m) 方法:
暴力建图,然后跑 dfs 求联通块即可,代码:
#include <bits/stdc++.h>
using namespace std;
int n,m,a[1010],v[1010];
vector <int> vc[1010];
void dfs(int r){
v[r]=1;
for (auto x:vc[r]){
if (!v[x]) dfs(x);
}
}
int main(){
cin>>n>>m;
for (int i=1; i<=m; i++){
cin>>a[i];
for (int j=1; j<i; j++){
if (!(a[i]&a[j])){
vc[i].push_back(j);
vc[j].push_back(i);
}
}
}int ans=0;
for (int i=1; i<=m; i++){
if (!v[i]){
ans++; dfs(i);
}
}cout<<ans;
return 0;
}
O(nm) 方法:
非常绝妙的虚点的题目(制造没有用的点解决问题)。
首先, 按位与为 的性质是:若 ~ 的值中,所有为 1 的位置记为集合 , 中所有为 1 的点记为集合 ,则满足 ⊂。
如何处理集合呢?可以使用 dfs,每次要枚举 的子集,就可以去掉一个值,然后一次类推。因为每一个子集都是删出来的。
最后给出实现方法——红蓝点法: