Solution :
比较经典的网络流构图了吧, 求一发最小割
Code:
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cstdio>
using namespace std;
typedef long long LL;
inline void read(int &x){x=0;char c;while((c=getchar())<'0'||c>'9');for(x=c-'0';(c=getchar())>='0'&&c<='9';x=(x<<1)+(x<<3)+c-'0');}
const int inf = 0x3f3f3f3f ;
const int N = 2505 ;
struct edge
{
int to, c, n;
}e[N * 8];
int head[N], tot = 1;
inline void addEdge(int x, int y, int c)
{
e[++tot] = (edge) {y, c, head[x]}, head[x] = tot;
}
namespace Max_Flow
{
int num[N], d[N], pa[N], cur[N];
int n, m, A, B, S, T;
void init_bfs()
{
static int que[N], l, r;
for (int i = 1; i < T; ++i) d[i] = T;
l = r = 0, d[que[++r] = T] = 0;
while (l < r)
{
int u = que[++l];
for (int p = head[u]; p; p = e[p].n) if (e[p ^ 1].c && d[e[p].to] > d[u] + 1)
d[e[p].to] = d[u] + 1, que[++r] = e[p].to;
}
}
int augment()
{
int ret = inf, x = T;
while (x != S)
{
ret = min(ret, e[pa[x]].c);
x = e[pa[x] ^ 1].to;
}
x = T;
while (x != S)
{
e[pa[x]].c -= ret, e[pa[x] ^ 1].c += ret;
x = e[pa[x] ^ 1].to;
}
return ret;
}
int Maxflow()
{
init_bfs();
for (int i = 1; i <= T; ++i) ++num[d[i]];
memcpy(cur, head, sizeof(int) * (T + 2));
int ret = 0, x = S;
while (d[S] < T)
{
if (x == T) ret += augment(), x = S;
bool ok = 0;
for (int p = cur[x]; p; p = e[p].n) if (e[p].c)
{
int to = e[p].to;
if (d[to] + 1 == d[x]) { ok = 1, cur[x] = pa[to] = p, x = to; break ; }
}
if (!ok)
{
if (!(--num[d[x]])) break ;
int mm = T + 1;
for (int p = head[x]; p; p = e[p].n) if (e[p].c) mm = min(mm, d[e[p].to]);
++num[d[x] = mm + 1], cur[x] = head[x];
if (x != S) x = e[pa[x] ^ 1].to;
}
}
return ret;
}
inline int id(int x, int y)
{
return (x - 1) * m + y;
}
void main()
{
static char ch[255];
read(n), read(m), read(A), read(B);
S = n * m + 1, T = S + 1;
for (int i = 1; i <= n; ++i)
{
scanf("%s", ch + 1);
for (int j = 1; j <= m; ++j)
{
int tmp = id(i, j);
if (ch[j] == '#')
addEdge(S, tmp, B), addEdge(tmp, S, 0);
else
addEdge(tmp, T, B), addEdge(T, tmp, 0);
if (i > 1)
addEdge(tmp, id(i - 1, j), A), addEdge(id(i - 1, j), tmp, A);
if (j > 1)
addEdge(tmp, id(i, j - 1), A), addEdge(id(i, j - 1), tmp, A);
}
}
printf("%d\n", Maxflow());
}
}
int main()
{
#ifdef LX_JUDGE
freopen("in.txt", "r", stdin);
#endif
Max_Flow::main();
return 0;
}