传送门

题意:

给出一个\(n*m\)的迷宫,有\(a\)个入口,\(b\)个出口。

现在有\(a\)个机器人都从入口出发,一开始方向默认为下,你可以选在在一些格子上面放置一个转向器,转向器有四种:

  • 向下走变为向右走;
  • 向下走变为向左走;
  • 向上走变为向右走;
  • 向上走变为向左走。

每个格子最多放一个转向器。

问最后是否存在一种方案,使得每个机器人都能到达从其中一个出口。

思路:

因为题目要求转向器只能接受固定方向,并且变为固定方向,所以有几个比较重要的观察:

  • 不存在两个机器人的路线共线;
  • 若一个格子上存在转向器,那么至多只能经过一个机器人;
  • 若一个格子上没有转向器,那么可以经过两个方向垂直的机器人。

观察一挺好证明,若存在两个机器人共方向,说明其中一个机器人经过转向器,而另一个没有经过,出现矛盾。后面几个yy一下应该好理解。

所以现在问题就是,一个格子只能横向经过或竖向经过,若经过转换器,只能经过一次,问能否使得\(a\)个机器人成功走到终点。

考虑网络流,我们将点拆成两类:一类是“水平”类点,另一类是“垂直”类点。那么一开始我们有水平和水平的相连,垂直的和垂直的相连,流量为\(1\)。

考虑经过转换器时,方向发生了变化,那么我们对于一个点,允许其向另一个方向转化,流量为\(1\)。

容易发现这样的建图刚好符合上面的要求。

PS:网上代码很多都是错的,因为没有考虑到障碍物的情况,注意一下最后到出口时,是否能到达\((n,x)\)这个点。

细节见代码:

#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
//#define Local
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 50005; #define INF 0x3f3f3f3f
template <class T>
struct Dinic{
struct Edge{
int v, next;
T flow;
Edge(){}
Edge(int v, int next, T flow) : v(v), next(next), flow(flow) {}
}e[N * 30];
int head[N], tot;
int dep[N];
void init() {
memset(head, -1, sizeof(head)); tot = 0;
}
void adde(int u, int v, T w, T rw = 0) {
e[tot] = Edge(v, head[u], w);
head[u] = tot++;
e[tot] = Edge(u, head[v], rw);
head[v] = tot++;
}
bool BFS(int _S, int _T) {
memset(dep, 0, sizeof(dep));
queue <int> q; q.push(_S); dep[_S] = 1;
while(!q.empty()) {
int u = q.front(); q.pop();
for(int i = head[u]; ~i; i = e[i].next) {
int v = e[i].v;
if(!dep[v] && e[i].flow > 0) {
dep[v] = dep[u] + 1;
q.push(v);
}
}
}
return dep[_T] != 0;
}
T dfs(int _S, int _T, T a) {
T flow = 0, f;
if(_S == _T || a == 0) return a;
for(int i = head[_S]; ~i; i = e[i].next) {
int v = e[i].v;
if(dep[v] != dep[_S] + 1) continue;
f = dfs(v, _T, min(a, e[i].flow));
if(f) {
e[i].flow -= f;
e[i ^ 1].flow += f;
flow += f;
a -= f;
if(a == 0) break;
}
}
if(!flow) dep[_S] = -1;
return flow;
}
T dinic(int _S, int _T) {
T max_flow = 0;
while(BFS(_S, _T)) max_flow += dfs(_S, _T, INF);
return max_flow;
}
}; Dinic <int> solve; int n, m, a, b;
char mp[105][105]; int id(int x, int y) {
return (x - 1) * m + y;
} bool ok(int x, int y) {
return x >= 1 && x <= n && y >= 1 && y <= m && mp[x][y] != '1';
} void run() {
solve.init();
cin >> n >> m >> a >> b;
int base = (n + 1) * m;
int s = 0, t = 2 * base + 1;
for(int i = 1; i <= n; i++) {
cin >> (mp[i] + 1);
}
for(int i = 1; i <= a; i++) {
int x; cin >> x;
solve.adde(s, id(1, x), 1);
}
for(int i = 1; i <= b; i++) {
int x; cin >> x;
solve.adde(id(n, x), t, 1);
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
if(mp[i][j] == '1') continue;
if(ok(i - 1, j)) solve.adde(id(i, j), id(i - 1, j), 1);
if(ok(i + 1, j)) solve.adde(id(i, j), id(i + 1, j), 1);
if(ok(i, j - 1)) solve.adde(id(i, j) + base, id(i, j - 1) + base, 1);
if(ok(i, j + 1)) solve.adde(id(i, j) + base, id(i, j + 1) + base, 1);
solve.adde(id(i, j), id(i, j) + base, 1);
solve.adde(id(i, j) + base, id(i, j), 1);
}
}
if(solve.dinic(s, t) == a) cout << "Yes" << '\n';
else cout << "No" << '\n';
} int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
#ifdef Local
freopen("../input.in", "r", stdin);
freopen("../output.out", "w", stdout);
#endif
int T; cin >> T;
while(T--) run();
return 0;
}

较完整题解:hhh

2019CCPC 秦皇岛 E.Escape的更多相关文章

  1. [CCPC2019秦皇岛] E. Escape

    [CCPC2019秦皇岛E] Escape Link https://codeforces.com/gym/102361/problem/E Solution 观察到性质若干然后建图跑最大流即可. 我 ...

  2. 2019CCPC秦皇岛 E题 Escape(网络流)

    Escape Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Su ...

  3. 2019-ccpc秦皇岛现场赛

    https://www.cnblogs.com/31415926535x/p/11625462.html 昨天和队友模拟了下今年秦皇岛的区域赛,,,(我全程在演 题目链接 D - Decimal 签到 ...

  4. 2019CCPC秦皇岛D题 Decimal

    Decimal Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total S ...

  5. 2019CCPC秦皇岛I题 Invoker(DP)

    Invoker Time Limit: 15000/12000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total ...

  6. 2019CCPC秦皇岛 F Forest Program

    队友过的:https://blog.csdn.net/liufengwei1/article/details/101632506 Forest Program Time Limit: 2000/100 ...

  7. 2019CCPC秦皇岛 J MUV LUV EXTRA(KMP)

    MUV LUV EXTRA Time Limit: 2000/1500 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)T ...

  8. 2019CCPC秦皇岛 K MUV LUV UNLIMITED(博弈)

    MUV LUV UNLIMITED Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Othe ...

  9. 2019CCPC秦皇岛自我反省&部分题解

    练了一年半了,第一次打CCPC,险些把队友坑了打铁,最后也是3题危险捡了块铜. 非常水的点双连通,我居然不相信自己去相信板子,唉,结果整来整去,本来半个小时能出的题,整到了3个小时,大失误呀,不然就可 ...

随机推荐

  1. 201871010111-刘佳华《面向对象程序设计(java)》第十一周学习总结

    201871010111-刘佳华<面向对象程序设计(java)>第十一周学习总结 实验九  泛型程序设计技术 实验时间 2019-11-8 1.实验目的与要求 (1) 理解泛型概念: (2 ...

  2. (day56)八、删除框、批量创建、分页器组件

    目录 一.ajax结合sweetalert实现删除按钮的动态效果 二.bulk_create批量插入数据 三.自定义分页器 (一)手动推导 (二)自定义分页器 (1)模板 (2)用法 一.ajax结合 ...

  3. linux 安装盘作为 repo

    1) CentOS 7.7 安装完之后, /etc/yum.repos.d 下面有很多.repo. 其中有一个CentOS-Media.repo. 编辑文件把enabled 改成 1 . 然后把其他. ...

  4. hdu6468 dfs剪枝 or char数组 or 构造

    http://acm.hdu.edu.cn/showproblem.php?pid=6468 题意 有一个序列,是1到n的一种排列,排列的顺序是字典序小的在前,那么第k个数字是什么?(\(1 \leq ...

  5. glade No package 'libxml-2.0' found

    ------------恢复内容开始------------ 今天突发奇想 root@Aja:~/下载/libxml2-master# glade 不会用纳 百度一下——————————>> ...

  6. django restful framework教程大全

    一. 什么是RESTful REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移” REST从资源的角 ...

  7. JAVA基础系列:反射

    1. 定义 在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这 种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. ...

  8. golang--单元测试综合实例

    实例说明: (1)一个Monster结构体,字段Name,Age,Skill (2)Monster有一个Store方法,可以将一个Monster对象序列化后保存在文件中: (3)Monster有一个R ...

  9. Vue devtool插件安装后无法使用,提示“vue.js not detected”的解决方法

    vue devtool下载 极简插件  github vue devtool安装 点击谷歌浏览器箭头所指图标-更多工具-扩展程序   ①:直接将后缀为crx的安装包拖进下图区域即可自动安装     ② ...

  10. php imagemagick 翻译目录

    图像处理(ImageMagick) 介绍 安装/配置 要求 安装 运行时配置 资源类型 预定义常数 例子 基本用法 Imagick - Imagick课 Imagick :: adaptiveBlur ...