zoj1002 FireNet 火力网 C++ 二分图匹配

来源:互联网 发布:win7网络连接配置错误 编辑:程序博客网 时间:2024/04/27 19:48

题目描述

给出一个N*N的网格,用'.'表示空地,用'X'表示墙。在网格上放碉堡,可以控制所在的行和列,但不能穿过墙。

问:最多能放多少个碉堡?


二分图匹配解法:将横向的联通块作为x部,纵向作为y部(如果只有一个格子就被堵死也算一个联通块)。如有相交则连边。每一条边实际对应了一个碉堡,如果有两条边指向同一个点,实际表示两个碉堡放在了同一个联通块,会产生冲突。所以求最大匹配数就对应了最大可能放的碉堡数。


这是我两年前写的辣鸡代码。丑的要死。。

#include<cstdio>#include<list>#include<cstring>using namespace std;int n, ans;char map[10][10];int xsum,ysum;int x[10][10];int y[10][10];int nx[400][3], ny[400][3];list<int> myl[1000];bool vis[1000];int c[1000];void init(){int i, j, k;for (i=1; i<=n; ++i)scanf("%s",map[i]+1);for (i=1; i<=n; ++i)for (j=1; j<=n; ++j)if (map[i][j]=='.'){++xsum;for (k=j; k<=n&&map[i][k]=='.'; ++k) x[i][k]=xsum;nx[xsum][0]=i,nx[xsum][1]=j,nx[xsum][2]=k-1;j=k;}for (j=1; j<=n; ++j)for (i=1; i<=n; ++i)if (map[i][j]=='.'){++ysum;for (k=i; k<=n&&map[k][j]=='.'; ++k) y[k][j]=ysum;ny[ysum][0]=j,ny[ysum][1]=i,ny[ysum][2]=k-1;i=k;}}void BuildGraph(){int i,j;for (i=1; i<=xsum; ++i)for (j=nx[i][1]; j<=nx[i][2]; ++j){int t=nx[i][0];if (y[t][j]){int t1=nx[i][0],t2=nx[i][1];myl[x[t1][t2]].push_front(y[t][j]+xsum);}}}bool dfs(int u){for (list<int>::iterator p=myl[u].begin(); p!=myl[u].end(); p++){        int v=*p;    if (!vis[v])    {    vis[v]=1;if (!c[v] || dfs(c[v])){c[u]=v, c[v]=u;return true;}    }     }return false;}void clear(){memset(x,0,sizeof x);memset(y,0,sizeof y);memset(nx,0,sizeof nx);memset(ny,0,sizeof ny);memset(map,0,sizeof map);memset(c,0,sizeof c);for (int i=1;i<900;i++)myl[i].clear();xsum=ysum=ans=0;}int main(){while (1){scanf("%d",&n);if (n==0) break;init();BuildGraph();for (int i=1; i<=xsum; ++i){memset(vis,0,sizeof vis);if (!c[i]) ans+=dfs(i);}printf("%d\n",ans);clear();}}


原创粉丝点击