Fire Net HDU - 1045
题意:
有一个矩阵。
其中的棋子(为了方便叫棋子吧)不能同行同列。(除非中间有墙)
问:最多放几个棋子。
思路:
- 缩点。
- 跑最大二分图匹配。(行块和列块进行匹配)
AC
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 1010;
int n ,cntx ,cnty ,cx[maxn] ,cy[maxn] ,tmp[15][15] ;
char s[15][15] ;
bool used[maxn] ,link[maxn][maxn];
void build()
{
memset(link,0,sizeof link);
memset(tmp,0,sizeof tmp);
cntx = 1;
for(int i = 0;i < n;++i)
{
for(int j = 0;j < n; ++j){
if(s[i][j] == 'X') ++cntx; //缩点
else tmp[i][j] = cntx;
}
if(s[i][n - 1]!='X') ++cntx;
}
cnty = 1;
for(int j = 0;j < n; ++j)
{
for(int i = 0;i < n;++i){
if(s[i][j] == 'X') ++cnty;
else link[tmp[i][j]][cnty] = 1;//link
}
if(s[n - 1][j] != 'X') ++cnty;
}
}
bool dfs(int u)
{
for(int v = 1;v <= cnty; ++v)
if(!used[v] && link[u][v])
{
used[v] = 1;
if(!cy[v] || dfs(cy[v]))
{
cx[u] = v ,cy[v] = u ;
return 1;
}
}
return 0;
}
void solve()
{
memset(cx,0,sizeof cx);
memset(cy,0,sizeof cy);
int ans = 0;
for(int i = 1;i <= cntx;++i)
if(!cx[i])
{
memset(used,0,sizeof(used));
ans += dfs(i);//最大匹配
}
printf("%d\n",ans);
}
int main()
{
while(~scanf("%d",&n) && n)
{
for(int i = 0;i < n;++i) scanf("%s",s[i]);
build();
solve();
}
return 0;
}