题意

给你一个\(N×M\)的草地,有高地有低地。

收割机从低地走到高地或者从高地走到低地都要花费用\(A\),你可以花费用\(B\)把一块高地变成低地,或者把一块低地变成高地。收割机每行每列都是必须要跑一趟的。

求最小花费。

解析

\(S\)向低地、高地向\(T\)建权为\(B\)的边,相邻的地之间建边权为\(A\)的边。

然后求最小割。

相同类型的地之间为什么也要建边呢?因为类型是可以改变的。

#include <bits/stdc++.h>
#define FOPI freopen("in.txt", "r", stdin)
#define FOPO freopen("out.txt", "w", stdout)
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f;
const int maxn = 50 * 50 + 1000;
const int maxm = 1e5 + 100; struct Edge
{
int to, next, cap, flow;
}edge[maxm]; int tot;
int head[maxn]; void init()
{
tot = 2;
memset(head, -1, sizeof(head));
} void build(int u, int v, int w, int rw = 0)
{
edge[tot].to = v; edge[tot].cap = w; edge[tot].flow = 0;
edge[tot].next = head[u]; head[u] = tot++; edge[tot].to = u; edge[tot].cap = 0; edge[tot].flow = 0;
edge[tot].next = head[v]; head[v] = tot++;
} int Q[maxn];
int dep[maxn], cur[maxn], sta[maxn]; bool bfs(int s, int t, int n)
{
int front = 0, tail = 0;
memset(dep, -1, sizeof(dep[0]) * (n+1));
dep[s] = 0;
Q[tail++] = s;
while(front < tail)
{
int u = Q[front++];
for (int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if (edge[i].cap > edge[i].flow && dep[v] == -1)
{
dep[v] = dep[u] + 1;
if (v == t) return true;
Q[tail++] = v;
}
}
}
return false;
} LL dinic(int s, int t, int n)
{
LL maxflow = 0;
while(bfs(s, t, n))
{
for (int i = 0; i < n; i++) cur[i] = head[i];
int u = s, tail = 0;
while(cur[s] != -1)
{
if (u == t)
{
int tp = inf;
for (int i = tail-1; i >= 0; i--)
tp = min(tp, edge[sta[i]].cap - edge[sta[i]].flow); //if (tp >= inf) return -1;
maxflow += tp; for (int i = tail-1; i >= 0; i--)
{
edge[sta[i]].flow += tp;
edge[sta[i]^1].flow -= tp;
if (edge[sta[i]].cap - edge[sta[i]].flow == 0) tail = i;
}
u = edge[sta[tail]^1].to;
}
else if (cur[u] != -1 && edge[cur[u]].cap > edge[cur[u]].flow
&& dep[u]+1 == dep[edge[cur[u]].to])
{
sta[tail++] = cur[u];
u = edge[cur[u]].to;
}
else
{
while(u != s && cur[u] == -1) u = edge[sta[--tail]^1].to;
cur[u] = edge[cur[u]].next;
}
}
}
return maxflow;
} int n, m, A, B;
int S, T;
char a[maxn][maxn]; int id(int i, int j) { return (i-1)*m + j; } int main()
{
//FOPI;
init(); scanf("%d%d%d%d", &n, &m, &A, &B);
S = 0, T = n*m+1; for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
{
scanf(" %c", &a[i][j]);
if (a[i][j] == '.') build(S, id(i, j), B);
else build(id(i, j), T, B); if (i > 1) build(id(i, j), id(i-1, j), A);
if (i < n) build(id(i, j), id(i+1, j), A);
if (j > 1) build(id(i, j), id(i, j-1), A);
if (j < m) build(id(i, j), id(i, j+1), A);
} LL ans = dinic(S, T, T+1);
printf("%lld\n", ans);
}

最新文章

  1. 远程连接mysql容易遇到的2个问题
  2. Effective Java 56 Adhere to generally accepted naming conventions
  3. Scanner中next()和nextline()读取字符串方法和区别
  4. myql查询创建表语句SHOW CREATE TABLE table_name
  5. 一步一步重写 CodeIgniter 框架 (7) —— Controller执行时将 Model获得的数据传入View中,实现MVC
  6. ORALCE 编译过程卡死解决方法。
  7. JavaSE学习总结(一)——Java基础
  8. 终于开始我的java旅程了!
  9. Alpha(5/10)
  10. 【转】VS2015详细安装步骤
  11. 如何将 jar 包导入Maven 本地仓库
  12. java 获取系统当前时间并格式化
  13. XMind 8 Update 7 Pro 激活码
  14. 牛腩学用MUI做手机APP
  15. 前端开发工程师 - 03.DOM编程艺术 - 期末考试
  16. Python 开发中easy_install的安装及使用
  17. Backbone.js 1.0.0源码架构分析(一)
  18. HTML5相册浏览插件
  19. Android之Application类用法
  20. Codeforces - 662A 思路巧妙的异或

热门文章

  1. 全栈工程师,也叫全端工程师,英文FullStackdevelopver。是指掌握多种技能,并能利用多种技能独立完成产品的人。
  2. JavaSE_3_面向对象
  3. Java语言程序设计(第三版)第二章课后习题答案(仅供参考)
  4. vue-cli之脚手架
  5. Miner3D Developer 开发工具
  6. 在Ubuntu环境下配置NIMH MEG Core Facility之CTF Tools
  7. Notification高级技巧
  8. Echarts图表学习
  9. hihocoder 1109 堆优化的Prim算法
  10. http请求头和相应头的作用