【题目链接】 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; }