如果不允许转化'#'和'.'的话,那么可以直接在'#'和'.'之间连容量为b的边,把所有'#'和一个源点连接,

所有'.'和一个汇点连接,流量不限,那么割就是建围栏(分割'#'和'.')的花费。

问题是'#'和'.'是可以转化的,由刚才的思路,可以联想到,当'#'可以转化成'.'的时候,那么就不需要在它和周围的'.'之间建围栏,

那么可以限制源点到'#'的容量为d,表示最多花费为d,对称地,限制'.'到汇点T容量为f。

然后跑最大流最小割就好了。

这题思路好神啊。。。仔细体会容量表示最多花费和最小割的关系

#include<bits/stdc++.h>
using namespace std; struct Edge
{
int v,cap,nxt;
};
const int maxv = +;
vector<Edge> edges;
#define PB push_back
int head[maxv],cur[maxv]; void AddEdge(int u,int v,int c)
{
edges.PB({v,c,head[u]});
head[u] = edges.size()-;
edges.PB({u,,head[v]});
head[v] = edges.size()-;
} int S = ,T = ;
int lv[maxv];
bool vis[maxv];
int q[maxv]; bool bfs()
{
memset(vis,,sizeof(vis));
int l = , r = ;
lv[S] = ; q[r++] = S; vis[S] = true;
while(r>l){
int u = q[l++];
for(int i = head[u]; ~i; i = edges[i].nxt){
Edge &e = edges[i];
if(!vis[e.v] && e.cap){
lv[e.v] = lv[u]+; vis[e.v] = true;
q[r++] = e.v;
}
}
}
return vis[T];
} int dfs(int u,int a)
{
if(u == T||!a) return a;
int flow = ,f;
for(int &i = cur[u]; ~i; i = edges[i].nxt){
Edge &e = edges[i];
if(lv[e.v] == lv[u]+ && (f = dfs(e.v,min(a,e.cap)))){
flow += f;
e.cap -= f;
edges[i^].cap += f;
a -= f;
if(!a) break;
}
}
return flow;
} const int INF = 0x3f3f3f3f;
int MaxFlow()
{
int flow = ;
while(bfs()){
memcpy(cur,head,sizeof(head));
flow += dfs(S,INF);
}
return flow;
} const int N = ;
char g[N][N+];
int id[N][N];
int h,w;
int d,f,b; int ID(int i,int j) { return i*w+j+; } void init()
{
scanf("%d%d%d%d%d",&w,&h,&d,&f,&b);
edges.clear();
for(int i = ; i < h; i++){
scanf("%s",g[i]);
for(int j = ; j < w; j++){
id[i][j] = ID(i,j);
}
}
memset(head,-,sizeof(head));
}
int dx[] = {,,,-};
int dy[] = {,-,,}; int main()
{
//freopen("in.txt","r",stdin);
int TestCase; scanf("%d",&TestCase);
while(TestCase--){
init();
int cost = ;
for(int i = ; i < h; i++){
for(int j = ; j < w; j++){
if(i == || i == h- || j == || j == w-){
if(g[i][j] == '.') cost += f;
AddEdge(S,id[i][j],INF);
}else {
if(g[i][j] == '#') AddEdge(S,id[i][j],d);
else AddEdge(id[i][j],T,f);
}
for(int k = ; k < ; k++){
int ni = i+dx[k], nj = j+dy[k];
if(ni<||ni>=h||nj<||nj>=w) continue;
AddEdge(id[i][j],id[ni][nj],b);
}
}
}
printf("%d\n",cost+MaxFlow());
}
return ;
}

最新文章

  1. Mac Pro 编译安装 Redis 的 PHP 客户端 phpredis
  2. 【CSS】创建布局
  3. Operational Amplifiers
  4. .gitignore 使用中注意的问题
  5. Tomcat中间件URL中文字符传递问题
  6. linux基础-第十单元 系统的初始化和服务
  7. hdu 4647 - Another Graph Game(思路题)
  8. 用rbenv给整个系统安装ruby(所有用户都可用)
  9. SQL Server 2008 清空删除日志文件
  10. eclipse+PyDev 中报错&quot;scrapy.spiders.Spider&quot; ,可用&quot;# @UndefinedVariable&quot;压制.
  11. Vim 缓冲区与窗口 操作
  12. Case when 的用法,简单Case函数
  13. 【django之用户认证】
  14. Spring Boot 2 - 初识与新工程的创建
  15. 个人笔记本安装多个jdk(jdk1.7,jdk1.8,jdk1.9,jdk10.0)出现的问题
  16. ethereum/EIPs-1193 Ethereum Provider JavaScript API 如metamask更新后的接口
  17. Can not find the tag library descriptor for &quot;http://java.sun.com/jsp/jstl/core&quot;
  18. Openfire注册流程代码分析
  19. 55. Jump Game (Array; Greedy)
  20. 第三百节,python操作redis缓存-其他常用操作,用于操作redis里的数据name,不论什么数据类型

热门文章

  1. PHP中的常用正则表达式集锦
  2. [教程心得] Flash AIR 调用exe/bat且可以传参
  3. 201621123016《Java程序设计》第二周学习总结
  4. Multi-University板块
  5. unity模型法线反转问题
  6. 如何在内网打洞使得能暴露mstsc端口
  7. 结束线程方法2 Java提供的中断机制
  8. Windows server 2003 + IIS6 搭建Asp.net MVC运行环境
  9. Vue 简单实用---代码可以直接用
  10. JavaScript 获取浏览器版本