【题目链接】 http://poj.org/problem?id=2724
【题目大意】
出一些01串,如果一个位置为*,则表示这个位置可以填0和1,产生不同的串
现在要匹配所有产生的串,你可以生成一些模式,生成的模式中最多可以有一个*,
表示可以同时匹配这个位置上的0或1,问你至少生成几个串,就能匹配所有的串
【题解】
我们先生成所有的串,我们对这些串进行相互比较,如果只有一位不同,
那么就连一条边,构图完成之后求这个图的最大独立集就是答案。
【代码】
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
const int MAX_V=2000;
const int INF=0x3f3f3f3f;
int V,match[MAX_V];
vector<int> G[MAX_V];
bool used[MAX_V];
void add_edge(int u,int v){
G[u].push_back(v);
G[v].push_back(u);
}
bool dfs(int v){
used[v]=1;
for(int i=0;i<G[v].size();i++){
int u=G[v][i],w=match[u];
if(w<0||!used[w]&&dfs(w)){
match[v]=u;
match[u]=v;
return 1;
}
}return 0;
}
int bipartite_matching(){
int res=0;
memset(match,-1,sizeof(match));
for(int v=0;v<V;v++){
if(match[v]<0){
memset(used,0,sizeof(used));
if(dfs(v))res++;
}
}return res;
}
void clear(){for(int i=0;i<V;i++)G[i].clear();}
const int MAX_N=30;
int N,M;
vector<int> op;
char s[MAX_N];
void solve(){
op.clear();
while(M--){
scanf("%s",s);
int t=0;
for(int i=0;i<N;i++)if(s[i]=='1')t+=1<<(N-i-1);
op.push_back(t);
for(int i=0;i<N;i++)if(s[i]=='*')t+=1<<(N-i-1);
op.push_back(t);
}sort(op.begin(),op.end());
op.erase(unique(op.begin(),op.end()),op.end());
V=op.size(); clear();
for(int i=0;i<V;i++){
for(int j=i+1;j<V;j++){
int diff=op[i]^op[j];
if((diff&(-diff))==diff)add_edge(i,j);
}
}printf("%d
",V-bipartite_matching());
}
int main(){
while(scanf("%d%d",&N,&M),N&&M)solve();
return 0;
}