解题思路:将点转化成边。求最小割,最小割=最大流。
#include <algorithm>
#include <stdio.h>
#include <queue>
#include <map>
#include <iostream>
#include <string.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int inf = 0x7f7f7f7f,N = 50000;
struct node{
int dot;
ll dis;
int next;
}e[N<<4];
int head[N<<4],cnt = 1;
int vis[N];
void add(int x,int y,ll z){
e[++cnt].dis = z;
e[cnt].dot = y;
e[cnt].next = head[x];
head[x] = cnt;
}
bool bfs(int s,int t){
queue<int>q;
memset(vis,0,sizeof vis);
q.push(s);
vis[s] = 1;
while(!q.empty()){
int u = q.front();q.pop();
for(int i = head[u];i;i = e[i].next){
int v = e[i].dot;
ll s = e[i].dis;
if(s&&!vis[v]){
q.push(v);
vis[v] = vis[u]+1;
if(v == t) return true;
}
}
}
return false;
}
ll dfs(int u,int low,int t){
if(u == t) return low;
for(int i = head[u];i;i = e[i].next){
int v = e[i].dot;
int s = e[i].dis;
if(v && vis[v] == vis[u]+1){
ll k = dfs(v,min(low,s),t);
if(k){
e[i].dis -= k;
e[i^1].dis += k;
return k;
}
}
}
return 0;
}
ll Dinic(int s,int t){
ll ans = 0;
while(bfs(s,t)){
ll flow;
while(flow = dfs(s,inf,t)){
ans += flow;
}
}
return ans;
}
char a[105][105];
void addedge(int u,int v,int z){
add(u,v,z);
add(v,u,0);
}
int op[4][2]={1,0,0,1,-1,0,0,-1};
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i = 1;i <= n;i++){
for(int j = 1;j <= m;j++){
cin >> a[i][j];
}
}
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
int u = (i - 1) * m + j;
if(a[i][j] == '#')continue;
else if(a[i][j] == '.'){
addedge(u, u + n * m, 1);
}else if(a[i][j] == 'A'){
addedge(0, u, inf);
}else if(a[i][j] == 'B'){
addedge(u, 2 * n * m + 1, inf);
}
for(int k = 0; k < 4; k++){
int vx = i + op[k][0];
int vy = j + op[k][1];
int v = (vx - 1) * m + vy;
if(vx>=1&&vx<=n&&vy>=1&&vy<=m&& a[vx][vy] != '#'){
if(a[i][j] == '.'){
addedge(u + n * m, v, inf);
}else {
addedge(u, v, inf);
}
}
}
}
}
ll ans = Dinic(0,2*n*m+1);
if(ans >= inf) ans = -1;
cout<<ans<<endl;
return 0;
}