传送门

题意:

给出一个\(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. table表格属性

  2. Class的使用,构造方法,实例属性和实例方法,静态属性和静态方法,this和super关键字,类的继承

    s6新增了一种定义对象实例的方法,Class(类)这个概念,作为对象的模板.class可以看作只是一个语法糖,通过class关键字,可以定义类.让对象原型的写法更加清晰.更像面向对象编程的语法. 一. ...

  3. Ultimate Chicken Horse GameProject第三次迭代成果文档

    经过三次迭代我们实现了游戏的基本功能 项目文档的github链接:https://github.com/k6tok12355/Ultimate-Chicken-Horse 下面是我们在第一次迭代中设定 ...

  4. Zuul中聚合Swagger的坑

    每个服务都有自己的接口,通过Swagger来管理接口文档.在服务较多的时候我们希望有一个统一的入口来进行文档的查看,这个时候可以在zuul中进行文档的聚合显示. 下面来看下具体的整合步骤以及采坑记录. ...

  5. 利用Python爬虫刷店铺微博等访问量最简单有效教程

    一.安装必要插件 测试环境:Windows 10 + Python 3.7.0 (1)安装Selenium pip install selenium (2)安装Requests pip install ...

  6. CSS的基础学习

    CSS学习 --------学习资源 http://www.csszengarden.com/ CSS语法检查http://jigsaw.w3.org/css-validator/ 配置CSS的方法: ...

  7. Django学习笔记(15)——中间件

    当Django处理一个Request的过程是首先通过中间件,然后再通过默认的URL方式进行的.我们可以在Middleware这个地方把所有Request拦截住,用我们自己的方式完成处理以后直接返回Re ...

  8. centos6系统资源限制

    1.限制用户CPU使用资源 /etc/security/limits.conf #主配置文件 /etc/security/limits.d/ #子模块配置文件 新建一个普通用户,并查看默认资源限制 [ ...

  9. python语法01

    在某.py文件中调用其他.py文件中的内容. 全局变量的使用. 线程的使用. if name == 'main': 的作用 新建两个python脚本文件 f1File.py ""& ...

  10. RookeyFrame在线新增模块

    今天给大家演示下在线新增模块的功能,在线新增模块跟在vs中写model实体类区别不大,线上新增少了手动初始化的过程,新增后模块同样具备新增.修改.删除.查看.导入.导出.复制.批量编辑.回收站.草稿箱 ...