POJ - 2226 Muddy Fields

题意:

  给出一个图, * 代表泥地, . 代表草地。用尽量少的木板盖住泥地,木板可以盖住任意长度的行或列,木板可以重叠但是不能盖住草地。求最少的木板数量。

题解:

  这道题有点像POJ3041的变形。在那道题之上把连着的行或列编上号,相连即可。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int maxn = 3000;
int r, c;
int cnt;
int map[55][55];
char s[55][55];
int vis[maxn];
int match[maxn];
vector<int> g[maxn];
void add_edge(int u, int v) {
    g[u].push_back(v);
    g[v].push_back(u);
}
bool dfs(int u) {
    vis[u] = 1;
    for(int i = 0; i < g[u].size(); i++) {
        int v = g[u][i], w=match[v];
        if(w<0 || !vis[w] && dfs(w)) {
            match[v] = u;
            match[u] = v;
            return true;
        }
    }
    return false;
}
int hungarian() {
    int res = 0;
    memset(match, -1, sizeof(match));
    for(int u = 1; u <= cnt; u++) {
        if(match[u] < 0) {
            memset(vis, 0, sizeof(vis));
            if(dfs(u)) res++;
        }
    }
    return res;
}
int main() {
    scanf("%d%d", &r, &c);
    for(int i = 0; i < r; i++) scanf("%s", s[i]);
    for(int i = 0; i < r; i++) {
        int flag = 0;
        for(int j = 0; j < c; j++) {
            if(flag==1 && s[i][j]=='*') map[i][j] = cnt;
            if(flag==0 && s[i][j]=='*') {
                flag = 1;
                map[i][j] = ++cnt;
            }
            if(s[i][j] == '.') flag = 0;
        }
    }
    for(int i = 0; i < c; i++) {
        int flag = 0;
        for(int j = 0; j < r; j++) {
            if(flag==1 && s[j][i]=='*') add_edge(cnt, map[j][i]);
            if(flag==0 && s[j][i]=='*') {
                flag = 1;
                cnt++;
                add_edge(cnt, map[j][i]);
            }
            if(s[j][i] == '.') flag = 0;
        }
    }
    printf("%d\n", hungarian());
}
View Code

 

posted @ 2018-04-02 22:47  Pneuis  阅读(138)  评论(0编辑  收藏  举报