Description
  从前有一个王国,这个王国的城堡是一个矩形,被分为M×N个方格。一些方格是墙,而另一些是空地。这个王国的国王在城堡里设了一些陷阱,每个陷阱占据一块空地。
  一天,国王决定在城堡里布置守卫,他希望安排尽量多的守卫。守卫们都是经过严格训练的,所以一旦他们发现同行或同列中有人的话,他们立即向那人射击。因此,国王希望能够合理地布置守卫,使他们互相之间不能看见,这样他们就不可能互相射击了。守卫们只能被布置在空地上,不能被布置在陷阱或墙上,且一块空地只能布置一个守卫。如果两个守卫在同一行或同一列,并且他们之间没有墙的话,他们就能互相看见。(守卫就像象棋里的车一样)
  你的任务是写一个程序,根据给定的城堡,计算最多可布置多少个守卫。
Input
  第一行两个整数M和N(1≤M,N≤200),表示城堡的规模。
  接下来M行N列的整数,描述的是城堡的地形。第i行j列的数用ai,j表示。
  ai,j=0,表示方格[i,j]是一块空地;
  ai,j=1,表示方格[i,j]是一个陷阱;
  ai,j=2,表示方格[i,j]是墙。
Output
  一个整数K,表示最多可布置K个守卫。
Sample Input
3 4
2 0 0 0
2 2 2 1
0 1 0 2
Sample Output
2
Source
from ymh


【分析】
转化问题为二分图最大匹配
和poj 2226 Muddy Fields差不多


【代码】

//巴蜀 P2311 宫廷守卫
#include<iostream>
#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define M(a) memset(a,0,sizeof a)
#define fo(i,j,k) for(i=j;i<=k;i++)
using namespace std;
vector <int> f[40005];
int map[202][202],heng[202][202],shu[202][202],link[40005];
int n,m,ans,h,l;
bool vis[40005];
inline bool dfs(int a)
{
for(register int i=0;i<f[a].size();i++)
{
int v=f[a][i];
if(!vis[v])
{
vis[v]=1;
if(!link[v] || dfs(link[v]))
{
link[v]=a;
return 1;
}
}
}
return 0;
}
int main()
{
int i,j,tmp=0;
scanf("%d%d",&n,&m);
fo(i,0,n) fo(j,0,m) map[i][j]=2;
fo(i,1,n) fo(j,1,m) scanf("%d",&map[i][j]);
fo(i,1,n)
fo(j,1,m)
{
if(map[i][j]<=1 && map[i][j-1]==2) tmp++;
if(map[i][j]<=1) heng[i][j]=tmp;
}
h=tmp,tmp=0;
fo(j,1,m)
fo(i,1,n)
{
if(map[i][j]<=1 && map[i-1][j]==2) tmp++;
if(map[i][j]<=1) shu[i][j]=tmp;
}
l=tmp,tmp=0;
fo(i,1,n) fo(j,1,m) if(map[i][j]==0) f[heng[i][j]].push_back(shu[i][j]);
fo(i,1,h)
{
M(vis);
if(dfs(i)) ans++;
}
printf("%d\n",ans);
return 0;
}