hdu5093 二分图最大匹配、

来源:互联网 发布:南通市物业管理网络 编辑:程序博客网 时间:2024/06/05 15:42

题解参考:http://blog.csdn.net/hpuhjh/article/details/47616779

题目大意:
给出一个n行m列的图,*代表海域,o代表冰水,#代表冰山,要想在海域中放置船,保证船与船之间不能相互看到,之间只要有山就不能看到,问最多能放多少船。
将一片最多只能放一个船的连续网格叫做‘块’。
以样例一为例
首先只考虑行,将每个块标号:将答案存入x [ ] [ ]
 1000
 0000
 2203
 0004
再此只考虑列,将每个块标号:将答案存入y [ ][ ]
 1000
 0000
 2304
 0004

这里写图片描述

#include<bits/stdc++.h>const int INF  = 0x3f3f3f3f;const int maxn = 5000001;const int Mod  = 1e9 + 7;#define ll long long#define mem(x,y) memset(x,y,sizeof(x))using namespace std;int x[55][55], y[55][55], cx[2555], cy[2555], xnum = 0, ynum;bool edge[2555][2555], vis[2555];char mp[55][55];void buildmp(int n, int m) {    int cnt = 0;    for (int i = 1; i <= n; i++) {        int sign = 0;        for (int j = 0; j < m; j++) {            if (mp[i][j] == '#') {                sign = 0;            } else if (mp[i][j] == '*') {                if (sign == 1) x[i][j] = cnt;                else x[i][j] = ++cnt;                sign = 1;            }        }        cnt++;    }    xnum = cnt;    cnt = 0;    for (int j = 0; j < m; j++) {        int sign = 0;        for (int i = 1; i <= n; i++) {            if (mp[i][j] == '#') {                sign = 0;            } else if (mp[i][j] == '*') {                if (sign == 1) y[i][j] = cnt;                else y[i][j] = ++cnt;                sign = 1;            }        }        cnt++;    }    ynum = cnt;    mem(edge, 0);    for (int i = 1; i <= n; i++) {        for (int j = 0; j < m; j++) {            if (mp[i][j] == '*') {                edge[ x[i][j] ] [ y[i][j] ] = 1;            }        }    }}int path(int u) {    for (int i = 1; i <= ynum; i++) {        if (edge[u][i] && !vis[i]) {            vis[i] = 1;            if (cy[i] == -1 || path(cy[i])) {                cx[u] = i;                cy[i] = u;                return 1;            }        }    }    return 0;}int getans(int n, int m) {    buildmp(n, m);    mem(cx, -1);    mem(cy, -1);    int ans = 0;    for (int i = 1; i <= xnum; i++) {        mem(vis , 0);        ans += path(i);    }    return ans;}int main() {    int T, n, m;    cin >> T;    while (T--) {        cin >> n >> m;        for (int i = 1; i <= n; i++)            scanf("%s", mp[i]);        cout << getans(n, m) << endl;    }}