“有这么多奇怪的限制关系一般都是网络流”
如果没有硬石头,那么左边行右边列,每个点代表一条边一遍匈牙利就可以
硬石头会把所在行和所在列隔开,对这一行这一列新建一个节点继续建图就好
我一定要在KOI前学会匈牙利!
/**************************************************************
Problem: 4554
User: di4CoveRy
Language: C++
Result: Accepted
Time:24 ms
Memory:1376 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <queue>
#define INF (1<<30)
#define N 3000
using namespace std;
struct Node{ int u; int cap; int rec; };
vector<Node> e[N];
int p[N],S,T,tot;
bool flag;
int row[N],col[N],cur[N],n,m,cnt;
char s[N];
void add_Node(int a,int b,int v)
{
Node tmp;
tmp.u = b;
tmp.cap = v;
tmp.rec = e[b].size();
e[a].push_back(tmp);
tmp.u = a;
tmp.cap = 0;
tmp.rec = e[a].size() - 1;
e[b].push_back(tmp);
}
bool BFS()
{
bool flag = false;
memset(p,0,sizeof(p));
memset(cur,0,sizeof(cur));
queue<int> q;
q.push(S);
p[S] = 1;
while (!q.empty()) {
int u = q.front();q.pop();
if (u == T) flag = true;
for (int i=0;i<(int)e[u].size();i++) {
int v = e[u][i].u;
int cp = e[u][i].cap;
if (p[v] == 0 && cp > 0) {
q.push(v);
p[v] = p[u] + 1;
}
}
}
return flag;
}
int DFS(int u,int flow) {
if (u == T) return flow;
int g = 0 , f = flow;
for (int i=cur[u];i<(int)e[u].size();i++) {
// cur[u] = i;
int v = e[u][i].u;
int cp = e[u][i].cap;
int tmp = 0;
if (p[v] == p[u]+1 && cp > 0 && (tmp = DFS(v,min(f,cp))) > 0) {
g += tmp;
f -= tmp;
e[u][i].cap -= tmp;
int rc = e[u][i].rec;
e[v][rc].cap += tmp;
}
}
return g;
}
int main() {
scanf("%d%d",&n,&m);
S = ++cnt , T = ++cnt;
for (int i=1;i<=n;i++) row[i] = ++cnt , add_Node(S,row[i],1);
for (int i=1;i<=m;i++) col[i] = ++cnt , add_Node(col[i],T,1);
for (int i=1;i<=n;i++) {
scanf("%s",s+1);
for (int j=1;j<=m;j++) {
if (s[j] == 'x') continue;
if (s[j] == '#') {
row[i] = ++cnt , add_Node(S,row[i],1);
col[j] = ++cnt , add_Node(col[j],T,1);
} else add_Node(row[i],col[j],1);
}
}
int ans = 0;
while (BFS()) ans += DFS(S,INF);
printf("%d\n",ans);
return 0;
}