题目链接

  要添最少的挡板使所有的'D'不存在到达网格外的路径.

以每个格子向四个方向中可以到达的格子连容量为1的边, 从源点向所有'D' 连容量为4的边,网格外的点向汇点连一条容量为4的边.

答案就是这个容量网络的最小割,即最大流.

/*最大流SAP邻接表思路:基本源于FF方法,给每个顶点设定层次标号,和允许弧。优化:1、当前弧优化(重要)。1、每找到以条增广路回退到断点(常数优化)。2、层次出现断层,无法得到新流(重要)。时间复杂度(m*n^2)
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <utility>
#include <vector>
#define ms(a,b) memset(a,b,sizeof a)
using namespace std;
const int INF = 6111;
struct node {int v, c, next;
} edge[100000];
int  pHead[100000], SS, ST, nCnt;
int n, m;
int g[200][200];
int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0};
//同时添加弧和反向边, 反向边初始容量为0
void addEdge (int u, int v, int c) {edge[++nCnt].v = v; edge[nCnt].c = c, edge[nCnt].next = pHead[u]; pHead[u] = nCnt;edge[++nCnt].v = u; edge[nCnt].c = 0, edge[nCnt].next = pHead[v]; pHead[v] = nCnt;
}
inline int SAP (int pStart, int pEnd, int N) {//层次点的数量  点的层次   点的允许弧     当前走过边的栈int numh[INF], h[INF], curEdge[INF], pre[INF];//当前找到的流, 累计的流量, 当前点, 断点, 中间变量int cur_flow, flow_ans = 0, u, neck, i, tmp;//清空层次数组,ms (h, 0); ms (numh, 0); ms (pre, -1);//将允许弧设为邻接表的任意一条边for (i = 0; i <= N; i++) curEdge[i] = pHead[i];numh[0] = N;//初始全部点的层次为0u = pStart;//从源点开始//如果从源点能找到增广路while (h[pStart] <= N) {//找到增广路if (u == pEnd) {cur_flow = 1e9;//找到当前增广路中的最大流量, 更新断点for (i = pStart; i != pEnd; i = edge[curEdge[i]].v)if (cur_flow > edge[curEdge[i]].c) neck = i, cur_flow = edge[curEdge[i]].c;//增加反向边的容量for (i = pStart; i != pEnd; i = edge[curEdge[i]].v) {tmp = curEdge[i];edge[tmp].c -= cur_flow, edge[tmp ^ 1].c += cur_flow;}flow_ans += cur_flow;//累计流量u = neck;//从断点开始找新的增广路
        }//找到一条允许弧for ( i = curEdge[u]; i != 0; i = edge[i].next)if (edge[i].c && h[u] == h[edge[i].v] + 1)     break;//继续DFSif (i != 0) {curEdge[u] = i, pre[edge[i].v] = u;u = edge[i].v;}//当前起点没有允许弧,从u找不到增广路else {//u所在的层次点减少一,且如果没有与当前点一个层次的点, 退出.if (0 == --numh[h[u]]) continue;//有与u相同层次的点, 更新u的层次 ,回到上一个点curEdge[u] = pHead[u];for (tmp = N, i = pHead[u]; i != 0; i = edge[i].next)if (edge[i].c)  tmp = min (tmp, h[edge[i].v]);h[u] = tmp + 1;++numh[h[u]];if (u != pStart) u = pre[u];}}return flow_ans;
}
inline void build() {char ch;scanf ("%d %d", &n, &m);ms (g, -1), ms (pHead, 0), nCnt = 1;for (int i = 1; i <= n; i++) {getchar();for (int j = 1; j <= m; j++) {ch = getchar();if (ch == '.')  g[i][j] = 0;if (ch == 'D') g[i][j] = 1;}}n += 2, m += 2;SS = n * m, ST = SS + 1;for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {int u = i * m + j;if (i == 0 || i == n - 1 || j == 0 || j == m - 1) {addEdge (u, ST, 4);continue;}if (g[i][j] == 0)  {for (int k = 0; k < 4; k++) {int x = i + dx[k], y = j + dy[k];int v = m * x + y;if (g[x][y] != 1)    addEdge (u, v, 1);}}if (g[i][j] == 1) {addEdge (SS, u, 4);for (int k = 0; k < 4; k++) {int x = i + dx[k], y = j + dy[k];int v = m * x + y;if (g[x][y] != 1 )     addEdge (u, v, 1);}}}}
}
int cs;
int main() {/*建图,前向星存边,表头在pHead[],边计数 nCnt.SS,ST分别为源点和汇点*/scanf ("%d", &cs);while (cs--) {build();printf ("%d\n", SAP (SS, ST, n * m + 1) );}return 0;
}

View Code

转载于:https://www.cnblogs.com/keam37/p/4293602.html

LA 6474 Drop Zone (最小割)相关推荐

  1. LA 3487 Duopoly 最小割

    传送门:LA 3487 Duopoly 题目大意:T公司和M公司想向政府申请一些资源的使用权.每一项申请包含一个资源列表和该公司愿意支付的金额.如果该申请得到批准,该公司将得到列表中所有资源的使用权. ...

  2. S-T平面图中利用最短路求最小割(BZOJ 1001)

    BZOJ 1001: [BeiJing2006]狼抓兔子 最小割 题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1001 现在小朋友们最喜欢 ...

  3. [学习笔记]最小割之最小点权覆盖最大点权独立集

    最小点权覆盖 给出一个二分图,每个点有一个非负点权 要求选出一些点构成一个覆盖,问点权最小是多少 建模: S到左部点,容量为点权 右部点到T,容量为点权 左部点到右部点的边,容量inf 求最小割即可. ...

  4. POJ 1966 Cable TV Network【无向图点连通度 最小割 E-K算法求最大流】

    题目描述: 给你一个无向图,问你最少删掉几个点,使这个图成不连通. 解题报告: 概念 (1)一个具有 N 个顶点的图,在去掉任意 k-1 个顶点后 (1<=K<=N) 所得的子图仍连通, ...

  5. 最小割 ---- 2021 ccpc 威海 H city-safety(最大利润 = 最大收益 - 最小花费(最小割))

    题目链接 题目大意: 一棵树,加强第 iii 个点有 wiw_iwi​ 的花费,而如果距离某 个点 ≤p≤ p≤p 的所有点都加强了,则会有 vpv_pvp​ 的收益,求最大净收益. 解题思路: 树形 ...

  6. 最小割 ---- 集合冲突模型 ----- P1646 [国家集训队]happiness

    题面: 高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友.这学期要分文理科了,每个同学对于选择文科与理科有着自己的喜悦值,而一对好朋友如果能同时选文科 ...

  7. 最小割 ---- 二分图最大独立集(集合冲突模型) ---- 骑士共存 方格取数(网络流24题)

    二分图独立集 定理: 二分图最大独立集=n - 二分图最大匹配 其实二分图独立集是特殊的一种最大权闭合子图.我们根据上文"收益"的思想,把选某个点的收益看为1,左部节点为正权点,右 ...

  8. 最小割 ---- 集合冲突模型 ---- AGC038 F - Two Permutations[详解]

    题目链接 题目大意: 给出两个排列P,QP,QP,Q.要求构造两个排列A,B.A,B.A,B. 要求:AiAiAi要么等于iii,要么等于PiPiPi;BiBiBi要么等于iii,要么等于QiQiQi ...

  9. 最小割 ---- 集合冲突模型

    集合冲突模型 1.问题形式 有 n 个物品和两个集合 S,T.将一个物品放入 S 集合会花费 ai,放入 T 集合会花费 bi.还有若干个形如 u,v,w 限制条件,表示如果 u 和 v 同时不在一个 ...

最新文章

  1. 小猿圈之Linux初学者掌握的基本命令
  2. Java---replace与replaceAll的区别
  3. 浅谈通信编程(二)--如何分离通信物理接口和应用程序
  4. 【咸鱼教程】基于系统时间的计时器DateTimer(不受FPS影响)
  5. 文档null一段 虚拟机操作
  6. 浅学习使用Ribbon 和 Feign的理解和使用
  7. [bzoj1191][HNOI2006]超级英雄Hero
  8. 宛如造句,小学生怎么用宛如造句?
  9. JFreechart 在linux下不显示及中文乱码问题
  10. 计算树结点路径的一种Javascript的实现
  11. java 反编译 报错_java反编译后再编译成class时提示缺少包
  12. 分库分表学习总结(1)——数据库中间件MyCat学习总结之MyCat入门简介
  13. linux查看gc日志,GC通用日志解读
  14. matlab中peaks是什么,Matlab中的peaks函数.doc
  15. RationalDMIS7.1自动测量圆+参考测量(汇总)
  16. [OpenHarmony RK3568] (二)基础开发
  17. 射频和无线技术入门--传统技术--7
  18. 向上取整⌈⌉和向下取整⌊⌋符号
  19. 爬虫ua设置及ip代理
  20. WxJava springboot微信支付商户直连分账使用总结

热门文章

  1. ios 绘制线框_iOS 绘制虚线框
  2. oracle增量合并存储过程,怎么将视图与存储过程里的逻辑合并
  3. 家庭NAS搭建实战之samba共享
  4. 深入理解JVM虚拟机(六):虚拟机类加载机制
  5. Java基础:由JVM内存模型详解线程安全
  6. dmx计算机,DMX是什么意思
  7. 计算最大回撤_看专业分析研究员如何一步步解读外汇市场结构,实现交易最大化盈利化!...
  8. php 算年龄,PHP计算年龄、
  9. nginx利用referer指令实现防盗链配置
  10. 如何利用nginx处理DDOS进行系统优化详解