Problem F: Landscaping

\[Time Limit: 1 s \quad Memory Limit: 256 MiB
\]

题意

题意是给出一个\(n*m\)的格子,其中一些是低海拔的,一些是高海拔的,然后有\(n+m\)辆推土车从左到右,从上到下推过去,推土车在不同高度的块之前走需要花费\(A\)元,也可以花费\(B\)元改变一个块的海拔

思路

这个网络流真的好骚啊...

先说建图怎么建图,建图分成三步

  1. 从源点到所有低海拔的块建一条\(B\)流量的边
  2. 从所有高海拔的块到汇点建一条\(B\)流量的边
  3. 对于所有块,想四个方向建一条\(A\)流量的边

考虑其中的一条流量。

源点\(\frac{B}{——>}\)低海拔\(\frac{A}{——>}\)高海拔\(\frac{B}{——>}\)汇点

如果\(A>B\),那么能跑出的最大流是\(B\),也就是花费\(B\)元把低海拔变为高海拔或者把高海拔变为低海拔,如果\(B>A\),那么跑出的最大流是\(A\),也就是花费\(A\)元从低海拔走到高海拔。

我们发现,这个最大流,一定是这三条边中的最小值。思考他们的意义,如果选择第一条边或第三条边,也就是把低海拔变为高海拔或者高海拔变为低海拔,那么这时候网络流中\(A\)被忽略了,也符合实际意义,已经改变了块的海拔,不用花费\(A\)元在不同块之间走。如果选择第二条边,也就是从低海拔走到高海拔,这时候\(B\)被忽略,也符合实际意义不修改这个块的海拔,而是直接走。

那么为什么一个块要对四个方向建边而不是向四个方向上存在海拔差的块建边呢?因为网络流跑的过程中,旁边的块可能发生了海拔变化,我们无法知道哪些发生了变化,所以都要建一个\(A\)的边。

所以在网络流跑的时候,由于限制条件的存在,他这样建边跑出来的最大流就是答案。

#include <map>
#include <set>
#include <list>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define lowbit(x) x & (-x)
#define mes(a, b) memset(a, b, sizeof a)
#define fi first
#define se second
#define pii pair<int, int>
#define INOPEN freopen("in.txt", "r", stdin)
#define OUTOPEN freopen("out.txt", "w", stdout) typedef unsigned long long int ull;
typedef long long int ll;
const int maxn = 1e5 + 10;
const int maxm = 1e5 + 10;
const ll mod = 1e9 + 7;
const ll INF = 1e18 + 100;
const int inf = 0x3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-8;
using namespace std; int n, m, A, B;
int cas, tol, T; struct Node{
int v, w;
int next;
} node[maxn];
int dis[4][2] = {1, 0, -1, 0, 0, 1, 0, -1};
char s[100][100];
int head[maxn];
int dep[maxn]; int getid(int x, int y) {
return (x-1)*m+y;
} void init() {
tol = 0;
mes(head, -1);
} void addnode(int u, int v, int w) {
node[tol].v = v;
node[tol].w = w;
node[tol].next = head[u];
head[u] = tol++;
} bool bfs(int src, int des) {
mes(dep, -1);
dep[src] = 0;
queue<int> q;
while(!q.empty()) q.pop();
q.push(src);
while(!q.empty()) {
int u = q.front();
q.pop();
if(u == des) return true;
for(int i=head[u]; ~i; i=node[i].next) {
int v = node[i].v;
if(dep[v] == -1 && node[i].w) {
dep[v] = dep[u]+1;
q.push(v);
}
}
}
return false;
} int dfs(int src, int des, int flow) {
if(src == des) return flow;
int ans = 0;
for(int i=head[src]; ~i; i=node[i].next) {
int v = node[i].v;
if(dep[v] == dep[src]+1 && node[i].w) {
int tmp = dfs(v, des, min(node[i].w, flow-ans));
node[i].w -= tmp;
node[i^1].w += tmp;
ans += tmp;
if(ans == flow) return ans;
}
}
if(!ans) dep[src] = -2;
return ans;
} int dinic(int src, int des) {
int ans = 0, tmp;
while(bfs(src, des)) {
while((tmp = dfs(src, des, inf)) > 0) {
ans += tmp;
}
}
return ans;
} int main() {
init();
scanf("%d%d%d%d", &n, &m, &A, &B);
int src = 0, des = n*m+1;
for(int i=1; i<=n; i++) {
scanf("%s", s[i]+1);
for(int j=1; j<=m; j++) {
if(s[i][j] == '.') {
addnode(src, getid(i, j), B);
addnode(getid(i, j), src, 0);
} else {
addnode(getid(i, j), des, B);
addnode(des, getid(i, j), 0);
}
}
}
for(int i=1; i<=n; i++) {
for(int j=1; j<=m; j++) {
for(int k=0; k<4; k++) {
int x = i+dis[k][0];
int y = j+dis[k][1];
if(x<1 || y<1 || x>n || y>m) continue;
addnode(getid(i, j), getid(x, y), A);
addnode(getid(x, y), getid(i, j), 0);
}
}
}
int ans = dinic(src, des);
printf("%d\n", ans);
return 0;
}

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

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

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

  2. Gym 101128F Landscaping(网络流)题解

    题意:n*m的地,从有高地和低地,从高地走到低地或者从低地走到高地花费a,把高地和低地互相改造一次花费b.现在要走遍每一行每一列,问最小花费 思路:超级源点连接所有低地,容量b:所有地向四周建边,容量 ...

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

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

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

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

  5. Gym - 100203I I WIN 网络流

    Gym - 100203I  I WIN 题意:一个n*m的矩阵包含W,I,N三种字符,问相邻的字符最多能组成不重叠的WIN. 思路:比赛的时候没有发现是网络流,,居然一度以为是二分图匹配,,写了一下 ...

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

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

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

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

  8. codeforce Gym 100203I I WIN (网络流)

    把'I'拆成容量为1一条边,一个入点一个出点,入点和相邻的'W'连一条容量为1的边,出点和相邻的'N'连一条容量为1,所有的'W'和源点连一条容量为1边,所有的'N'和汇点连一条容量为1的边,表示只能 ...

  9. codeforces gym 100357 J (网络流)

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

随机推荐

  1. Visual Studio pro key license 2019

    仅供学习交流使用,勿用作其他用途!!!!   Visual Studio 2019 Enterprise BF8Y8-GN2QH-T84XB-QVY3B-RC4DF Visual Studio 201 ...

  2. Android.mk文件官方使用说明

    本页介绍了 ndk-build 所使用的 Android.mk 编译文件的语法. 概览 Android.mk 文件位于项目 jni/ 目录的子目录中,用于向编译系统描述源文件和共享库.它实际上是编译系 ...

  3. Fiddler手机抓包不完全记录

    准备工作: 1.必须确保安装fiddler的电脑和手机在同一个wifi环境下 备注:如果电脑是笔记本当然最好;如果电脑用的是台式机,可以安装一个随身wifi,来确保台式机和手机在同一wifi环境下   ...

  4. java学习:循环结构的使用规则和注意事项

    循环结构的基本组成部分,一般可分为四部分: 初始化语句:在循环开始最初执行,而且只做唯一一次 条件判断:如果成立,则循环继续:如果不成立,则循环退出. 循环体:重复要做的事情内容,若干行语句. 进步语 ...

  5. PriorityQueue详解

    美人如斯!好好看文章! 前言 java中关于Queue队列的实现繁多(关于Queue可以移步至我的另一篇文章:<Queue介绍>),每种实现根据自身的特性都有相应的应用场景.这里我们就来聊 ...

  6. golang ---查看进程(Windows)

    package main import ( "fmt" "os" "os/exec" "strconv" "s ...

  7. Java 8 HashMap 源码解析

    HashMap 使用数组.链表和红黑树存储键值对,当链表足够长时,会转换为红黑树.HashMap 是非线程安全的. HashMap 中的常量 static final int DEFAULT_INIT ...

  8. 怎样调节Eclipse中的字体大小?

    window->perference->appearance->colors and font->text font edit

  9. dotnet core系列之Background tasks with hosted services (后台任务)

    这篇简单讲asp.net core 中的后台任务 用到的包: Microsoft.AspNetCore.App metapackage 或者加入 Microsoft.Extensions.Hostin ...

  10. 动画重定向技术分析及其在Unity中的应用

    前言 笔者新的手游项目使用Unity引擎,动画部分要使用重定向技术来实现动画复用.笔者之前在大公司工作的时候对这块了解比较深入,读过Havok引擎在这部分的实现源码,并基于自己的理解,在公司自研的手游 ...