HDU 5093 Battle ships(二分图)

来源:互联网 发布:手机恶作剧软件骑马 编辑:程序博客网 时间:2024/06/06 02:08

很经典的二分图匹配问题。

对于这个问题,我们只需要遍历两遍图,来建立一个二分图。原则为,如果这里有个#,说明这一行要拆成两行或者更多,这一列要拆成两列或者更多。

二分图建图方法强烈推荐百度一下,二分图最大匹配及常用建图方法。

代码如下:

#include<bits/stdc++.h>using namespace std;const int MAXN = 55;int uN, vN;int n, m;  //u,v数目char graph[MAXN][MAXN];int row[MAXN][MAXN], column[MAXN][MAXN];int G[2505][2505];//编号是0~n-1的 int linker[2505];bool used[2505];bool dfs(int u){    int v;    for(v = 0; v < vN; v++)        if(G[u][v] && !used[v])        {            used[v] = true;            if(linker[v] == -1 || dfs(linker[v]))            {                linker[v] = u;                return true;            }            }      return false;  }    int hungary(){    int res = 0;    int u;    memset(linker, -1, sizeof(linker));    for(u = 0; u < uN; u++)    {        memset(used, 0, sizeof(used));        if(dfs(u))  res++;    }     return res;   }     int main(){int T;cin >> T;while(T--) {bool flag = 0;int k1 = 0, k2 = 0;memset(row, -1, sizeof(row));memset(column, -1, sizeof(column));memset(G, 0, sizeof(G));cin >> n >> m;for(int i = 0; i < n; i++) scanf("%s", &graph[i]);for(int i = 0; i < n; i++) {for(int j = 0; j < m; j++) {if(graph[i][j] == '#') {k1++;while(j < m && graph[i][j] == '#') {j++;}j--;} else if (graph[i][j] == '*'){row[i][j] = k1;}}k1++;}for(int i = 0; i < m; i++) {for(int j = 0; j < n; j++) {if(graph[j][i] == '#') {k2++;while(j < n && graph[j][i] == '#') {j++;}j--;} else if (graph[j][i] == '*'){column[j][i] = k2;}}k2++;}for(int i = 0; i < m; i++) {for(int j = 0; j < n; j++) {if(row[i][j] != -1) {G[row[i][j]][column[i][j]] = 1;}}}uN = k1 + 1;vN = k2 + 1;cout << hungary() << endl;}return 0;}


原创粉丝点击