您的位置:首页 > 其它

UVA-1663 Purifying Machine (最大匹配数)

2016-01-18 19:53 267 查看
题目大意:每一个01串中最多含有一个‘*’,‘*’既可表示0也可表示1,给出一些等长的这样的01串,问最少能用多少个这样的串表示出这些串。如:000、010、0*1表示000、010、001、011,最少只需用00*、01*这两个即可表示出来。

题目分析:如果有两个串只有一个位置上的数字不同,就可以用*代替这个位置上的数,这样就能把两个串用一个串表示出来。因为要找最少的数目,当然‘*’用的越多越好,也就是说只需找出最多的对数,然后再加上不用‘*’表示的串的数目便是最小值。

代码如下:

# include<iostream>
# include<cstdio>
# include<vector>
# include<cstring>
# include<algorithm>
using namespace std;

vector<int>b;
int vis[1005];
int n,m,a[1500][1500],s[1500],t[1005];
int A[11]={1,2,4,8,16,32,64,128,256,512,1024};

void f(string p)
{
int r=0;
for(int i=0;i<m;++i)
r=r*2+p[i]-'0';
b.push_back(r);
}

bool ok(int x,int y)
{
int z=x^y;
for(int i=0;i<11;++i)
if(z==A[i]) return true;
return false;
}

void setG()
{
memset(a,0,sizeof(a));
for(int i=0;i<n;++i)
for(int j=i+1;j<n;++j)
if(ok(b[i],b[j])) a[i][j]=a[j][i]=1;
}

bool match(int u)
{
for(int v=0;v<n;++v){
if(!a[u][v]) continue;
if(vis[v]) continue;
vis[v]=1;
if(t[v]==-1||match(t[v])){
t[v]=u;
s[u]=v;
return true;
}
}
return false;
}

void solve()
{
memset(s,-1,sizeof(s));
memset(t,-1,sizeof(t));
int ans=0;
for(int i=0;i<n;++i)
if(s[i]==-1){
memset(vis,0,sizeof(vis));
if(match(i)) ++ans;
}
ans/=2;
for(int i=0;i<n;++i)
if(t[i]==-1) ++ans;
printf("%d\n",ans);
}

int main()
{
string p;
while(scanf("%d%d",&m,&n)&&(n+m))
{
b.clear();
for(int i=0;i<n;++i){
cin>>p;
int j;
for(j=0;j<m;++j) if(p[j]=='*') break;
if(j==m) f(p);
else{
p[j]='0';
f(p);
p[j]='1';
f(p);
}
}
sort(b.begin(),b.end());
n=unique(b.begin(),b.end())-b.begin();
setG();
solve();
}
return 0;
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: