题意:n*m的地,从有高地和低地,从高地走到低地或者从低地走到高地花费a,把高地和低地互相改造一次花费b。现在要走遍每一行每一列,问最小花费

思路:超级源点连接所有低地,容量b;所有地向四周建边,容量a;高地连接超级汇点,容量b。假如sum(a) > b,那么流出b,即这个地改造;假如sum(a) < b,那么就不改造。

代码:

#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include <iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 50 * 50 + 10;
const int M = maxn * 30;
const ull seed = 131;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
struct Edge{
int to, next, flow, cap;
}edge[maxn * 10];
int tot;
int head[maxn];
int gap[maxn], dep[maxn], pre[maxn], cur[maxn];
void init(){
tot = 0;
memset(head, -1, sizeof(head));
}
void addEdge(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 = rw;
edge[tot].flow = 0;
edge[tot].next = head[v];
head[v] = tot++;
}
int sap(int start, int end, int N){
memset(gap, 0, sizeof(gap));
memset(dep, 0, sizeof(dep));
memcpy(cur, head, sizeof(head));
int u = start;
pre[u] = -1;
gap[u] = N;
int ans = 0;
while(dep[start] < N){
if(u == end){
int Min = INF;
for(int i = pre[u]; i != -1; i = pre[edge[i ^ 1].to]){
Min = min(Min, edge[i].cap - edge[i].flow);
}
for(int i = pre[u]; i != -1; i = pre[edge[i ^ 1].to]){
edge[i].flow += Min;
edge[i ^ 1].flow -= Min;
}
u = start;
ans += Min;
continue;
}
bool flag = false;
int v;
for(int i = cur[u]; i != -1; i = edge[i].next){
v = edge[i].to;
if(edge[i].cap - edge[i].flow && dep[v] + 1 == dep[u]){
flag = true;
cur[u] = pre[v] = i;
break;
}
}
if(flag){
u = v;
continue;
}
int Min = N;
for(int i = head[u]; i != -1; i = edge[i].next){
if(edge[i].cap - edge[i].flow && dep[edge[i].to] < Min){
Min = dep[edge[i].to];
cur[u] = i;
}
}
gap[dep[u]]--;
if(!gap[dep[u]]) return ans;
dep[u] = Min + 1;
gap[dep[u]]++;
if(u != start) u = edge[pre[u] ^ 1].to;
}
return ans;
}
char mp[maxn][maxn];
int n, m;
int getid(int x, int y){
return (x - 1) * m + y;
}
int to[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};
int main(){
int a, b;
scanf("%d%d", &n, &m);
scanf("%d%d", &a, &b);
int s = n * m + 1, e = n * m + 2;
init();
for(int i = 1; i <= n; i++){
scanf("%s", mp[i] + 1);
for(int j = 1; j <= m; j++){
if(mp[i][j] == '.'){
addEdge(s, getid(i, j), b);
}
else{
addEdge(getid(i, j), e, b);
}
}
}
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
for(int k = 0; k < 4; k++){
int x = i + to[k][0];
int y = j + to[k][1];
if(x < 1 || y < 1 || x > n || y > m) continue;
addEdge(getid(i, j), getid(x, y), a);
}
}
}
int ans = sap(s, e, n * m + 2);
printf("%d\n", ans);
return 0;
}

Gym 101128F Landscaping(网络流)题解的更多相关文章

  1. Gym - 101128F Landscaping(网络流)

    题意 给你一个\(N×M\)的草地,有高地有低地. 收割机从低地走到高地或者从高地走到低地都要花费用\(A\),你可以花费用\(B\)把一块高地变成低地,或者把一块低地变成高地.收割机每行每列都是必须 ...

  2. 【最小割】【Dinic】Gym - 101128F - Landscaping

    http://blog.csdn.net/lxy767087094/article/details/68942422 #include<cstdio> #include<cstrin ...

  3. Landscaping Gym - 101128F (网络流)

    Problem F: Landscaping \[ Time Limit: 1 s \quad Memory Limit: 256 MiB \] 题意 题意是给出一个\(n*m\)的格子,其中一些是低 ...

  4. Gym 101128F Sheldon Numbers(网络流)

    [题目链接] http://codeforces.com/gym/101128/attachments [题目大意] 给出一张地图,分为高地和低地,高低地的交界线上划有红线, 现在要开小车跨过每条红线 ...

  5. Kuangbin 带你飞专题十一 网络流题解 及模版 及上下界网络流等问题

    首先是几份模版 最大流:虽然EK很慢但是优势就是短.求最小割的时候可以根据增广时的a数组来判断哪些边是割边.然而SAP的最大流版我只会套版,并不知道该如何找到这个割边.在尝试的时候发现了一些问题.所以 ...

  6. 【bzoj4439】[Swerc2015]Landscaping 网络流最小割

    题目描述 FJ有一块N*M的矩形田地,有两种地形高地(用‘#’表示)和低地(用‘.’表示) FJ需要对每一行田地从左到右完整开收割机走到头,再对每一列从上到下完整走到头,如下图所示 对于一个4*4的田 ...

  7. C - Portals Gym - 102006C (网络流最小割)

    题目链接:https://cn.vjudge.net/contest/283918#problem/C 题目大意:T个测试数据,然后给你一个字符串,每一个字符串包括‘s’,‘t’,‘o’,‘#’,‘. ...

  8. codeforces gym 100357 J (网络流)

    题目大意 有n种物品,m种建筑,p个人. n,m,p∈[1,20] 每种建筑需要若干个若干种物品来建造.每个人打算建造一种建筑,拥有一些物品. 主角需要通过交易来建造自己的建筑,交易的前提是对方用多余 ...

  9. Gym 100733J Summer Wars 题解:灵活运用扫描线的思想

    题意: 给你n个点,m个横着的线段.你能够横移这些线段,可是这些线段的相对位置不能改变.假设一个点,在它的正上方和和正下方都有线段(包含线段的终点).则这个点被视为被"屏蔽".问通 ...

随机推荐

  1. Java流程控制与Scanner类的使用

    Java流程控制与Scanner类的使用 Scanner类 Scanner类可以使程序接受键盘输入,实现人机交互 一个完整的Scanner的使用例子: //创建一个扫描器对象,用于接收键盘数据 Sca ...

  2. Linq.Expressions扩展ExpressionExtension

    手上有一个以前项目用到的.NET工具类封装的DLL. 正好又想试一下动态LAMBDA表达式,用.NET Reflector看一下源码. public static class ExpressionEx ...

  3. 前端面试之CSS权重问题!

    前端面试之CSS权重问题! 下面的权重按照从小到大来排列! 1.通用选择器(*) 2.元素(类型)选择器 权重1 3.类选择器 权重10 4.属性选择器 5.伪类 6.ID 选择器 权重100 7.内 ...

  4. JavaScript中创建对象的三种方式!

    JavaScript中创建对象的三种方式! 第一种 利用对象字面量! // 创建对象的三种方式! // 1 对象字面量. var obj = { // 对象的属性和方法! name: 'lvhang' ...

  5. Mybatis报错:Could not find resource mybatis-conf.xml

    Mybatis报错:Could not find resource mybatis-conf.xml 报错截图: 报错内容: java.io.IOException: Could not find r ...

  6. 长连接开发踩坑之netty OOM问题排查实践

    https://mp.weixin.qq.com/s/jbXs7spUCbseMX-Vf43lPw 原创: 林健  51NB技术  2018-07-13

  7. Centos GitLab 配置

    如果重启之后,gitlab-ctl restart报"runsv no running"错,先运行下面命令 systemctl start gitlab-runsvdir.serv ...

  8. 文件夹copy器(多进程版)

    import multiprocessing import os import time import random def copy_file(queue, file_name,source_fol ...

  9. Java服务端性能优化

    <Java程序性能优化>说性能优化包含五个层次:设计调优.代码调优.JVM调优.数据库调优.操作系统调优. 常用的几个代码优化方案: 使用单例 对于IO处理.数据库连接.配置文件解析加载等 ...

  10. spark SQL (二) 聚合

    聚合内置功能DataFrames提供共同聚合,例如count(),countDistinct(),avg(),max(),min(),等.虽然这些功能是专为DataFrames,spark SQL还拥 ...