zoukankan      html  css  js  c++  java
  • POJ 2226 Muddy Fields (最小点覆盖集,对比POJ 3041)

    题意

    给出的是N*M的矩阵,同样是有障碍的格子,要求每次只能消除一行或一列中连续的格子,最少消除多少次可以全部清除。

    思路

    相当于POJ 3041升级版,不同之处在于这次不能一列一行全部消掉,那些非障碍的格子不能消。 但是我们还是要抓住关键点:每个格子必须消除,要么以行消,要么以列消。并且我们发现如果以行消得话,一定是以这连续障碍行的最左端为起点,同理列是以最上端为起点。那么我们就又把消除方式变成两种了。这时就可以把障碍当作边,两种覆盖方式分别作为两断点,求二分图最小点覆盖集。 行列方式的起点共有R*C种,即二分图两个点集均需要R*C个点。并且注意这题RC好像不止50= =……我的二分图点大小开到2000才从RE变成AC……

    代码

     
    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;
    
    char map[MAXV][MAXV];
    int main(){
    	//freopen("test.in", "r", stdin);
    	//freopen("test.out", "w", stdout);
        int r, c;
        scanf("%d %d", &r, &c);
        getchar();
        match.init(r*c*2);
        for (int i = 0; i < r; i ++){
            for (int j = 0; j < c; j ++){
                scanf("%c", &map[i][j]);
                if (map[i][j] == '*'){
                    int k = j - 1, l = i -1;
                    while(k >= 0 && map[i][k] == '*'){
                        k --;
                    }
                    k ++;
                    while(l >= 0 && map[l][j] == '*'){
                        l --;
                    }
                    l ++;
                    match.add_uedge(i*c+k+1, r*c+l*c+j+1);
                }
            }
            getchar();
        }
        //match.print_edge();
        printf("%d
    ", match.hungary());
    	return 0;
    }
    
  • 相关阅读:
    SpringBoot集成MyBatisPlus
    Android 图片混排富文本编辑器控件
    Android 图片压缩器
    python中yield用法
    ubuntu下tesseract 4.0安装及参数使用
    Linux 命令行命令及参数辨异
    一题多解 —— linux 日志文件(log)reload 重新载入
    python中list用法及遍历删除元素
    计算机科学 —— 时间戳(timestamp)
    ubuntu中使用apt-get安装zbar
  • 原文地址:https://www.cnblogs.com/AbandonZHANG/p/4114291.html
Copyright © 2011-2022 走看看