zoukankan      html  css  js  c++  java
  • POJ 2724 Purifying Machine (二分图匹配)

    题意

    给定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;
    }
    
  • 相关阅读:
    java表格的使用 单元格绘制二
    Java表格的简单使用一
    Servlet接口五种方法介绍
    C# 图片识别
    asp.net 使用rabbitmq事例
    Windows下安装使用python的Flask框架
    python中闭包的理解
    sql中遍历字符串
    asp.net mvc easyui tree
    c# Castle Windsor简单例子
  • 原文地址:https://www.cnblogs.com/AbandonZHANG/p/4114077.html
Copyright © 2011-2022 走看看