题意
给定m个长度为n的01串(*既表示0 or 1。如*01表示001和101)。现在要把这些串都删除掉,删除的方法是:①一次删除任意指定的一个;②如果有两个串仅有一个字符不同,则可以同时删除这两个。求最少要多少次可以删完,并且同一个串不能删两次。
思路
我们用点表示一个串,如果两个串之间只有一个字符不同,那么这两个串之间连接一条,最大匹配数就是节省的次数。
因为每个串中的1为奇数的串之间是不能匹配的(不可能只有1个不同),同理,偶数也是。所以,可以按照1的奇偶性把数据分成2份,所以是一个二分图匹配。然后答案就是所有串数 - 最大匹配数。
代码
#include
#include
#include
#include
#include
#include
#define MID(x,y) ((x+y)/2)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int MAXV = 2005; //N1+N2
vector adj[MAXV];
struct MaximumMatchingOfBipartiteGraph{
int vn;
void init(int n){ //二分图两点集点的个数
vn = n;
for (int i = 0; i <= vn; i ++) adj[i].clear();
}
void add_uedge(int u, int v){
adj[u].push_back(v);
adj[v].push_back(u);
}
bool vis[MAXV];
int mat[MAXV]; //记录已匹配点的对应点
bool cross_path(int u){
for (int i = 0; i < (int)adj[u].size(); i ++){
int v = adj[u][i];
if (!vis[v]){
vis[v] = true;
if (mat[v] == 0 || cross_path(mat[v])){
mat[v] = u;
mat[u] = v;
return true;
}
}
}
return false;
}
int hungary(){
mem(mat, 0);
int match_num = 0;
for (int i = 1; i <= vn; i ++){
mem(vis, 0);
if (!mat[i] && cross_path(i)){
match_num ++;
}
}
return match_num;
}
void print_edge(){
for (int i = 1; i <= vn; i ++){
for (int j = 0; j < (int)adj[i].size(); j ++){
printf("u = %d v = %d
", i, adj[i][j]);
}
}
}
}match;
vector s;
int main(){
//freopen("test.in", "r", stdin);
//freopen("test.out", "w", stdout);
int n, m;
while(scanf("%d %d", &n, &m), n+m){
getchar();
s.clear();
for (int i = 1; i <= m; i ++){
char tmps[15];
scanf("%s", tmps);
int star = -1;
for (int j = 0; j < n; j ++){
if (tmps[j] == '*'){
star = j;
break;
}
}
if (star == -1){
if (find(s.begin(), s.end(), tmps) == s.end())
s.push_back(string(tmps));
}
else{
tmps[star] = '0';
if (find(s.begin(), s.end(), tmps) == s.end())
s.push_back(string(tmps));
tmps[star] = '1';
if (find(s.begin(), s.end(), tmps) == s.end())
s.push_back(string(tmps));
}
}
match.init(s.size());
for (int i = 0; i < s.size(); i ++){
for (int j = 0; j < i; j ++){
int dif = 0;
for (int k = 0; k < n; k ++){
if (s[i][k] != s[j][k]){
dif ++;
if (dif > 1)
break;
}
}
if (dif == 1){
match.add_uedge(j+1, i+1);
}
}
}
printf("%d
", s.size() - match.hungary());
}
return 0;
}