2019CCPC 秦皇岛 E.Escape
题意:
给出一个\(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的更多相关文章
- [CCPC2019秦皇岛] E. Escape
[CCPC2019秦皇岛E] Escape Link https://codeforces.com/gym/102361/problem/E Solution 观察到性质若干然后建图跑最大流即可. 我 ...
- 2019CCPC秦皇岛 E题 Escape(网络流)
Escape Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Su ...
- 2019-ccpc秦皇岛现场赛
https://www.cnblogs.com/31415926535x/p/11625462.html 昨天和队友模拟了下今年秦皇岛的区域赛,,,(我全程在演 题目链接 D - Decimal 签到 ...
- 2019CCPC秦皇岛D题 Decimal
Decimal Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total S ...
- 2019CCPC秦皇岛I题 Invoker(DP)
Invoker Time Limit: 15000/12000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total ...
- 2019CCPC秦皇岛 F Forest Program
队友过的:https://blog.csdn.net/liufengwei1/article/details/101632506 Forest Program Time Limit: 2000/100 ...
- 2019CCPC秦皇岛 J MUV LUV EXTRA(KMP)
MUV LUV EXTRA Time Limit: 2000/1500 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)T ...
- 2019CCPC秦皇岛 K MUV LUV UNLIMITED(博弈)
MUV LUV UNLIMITED Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Othe ...
- 2019CCPC秦皇岛自我反省&部分题解
练了一年半了,第一次打CCPC,险些把队友坑了打铁,最后也是3题危险捡了块铜. 非常水的点双连通,我居然不相信自己去相信板子,唉,结果整来整去,本来半个小时能出的题,整到了3个小时,大失误呀,不然就可 ...
随机推荐
- 《RocketMQ》
作为一款消息中间件,RocketMQ需要解决的技术问题其实在分布式系统领域中都有所体现.首先如果将分布式系统的领域按照分布式通信.分布式存储.分布式计算以及分布式管理这四大部分进行划分,其实就会发现在 ...
- 突然看到原来除了jar包还有war包啊?????
先来说说区别: 首先,jar包呢,是一个压缩文件,可以由很多文件压缩而成,,简单来说就是,jar包是别人写好的一些类,然后对这些类 进行打包,这就是jar包,你可以直接用这些 jar包,使用里面的类 ...
- session未释放
客户反映一个关于session的bug,说有了1,2天以后,就无法登陆了. 我们这边试了好几天,都没有出现类似问题,后来没办法,只能远程开会,7点左右和他们通话,偶然发现他们居然直接关remote d ...
- 在实际工作中使用requests+unittest进行接口测试
之前学习python做接口测试时,用的时requests+excel的方式来进行接口测试,后来在工作中也用unittest来做了一个项目的接口测试,接口测试用例完全基于unittest来编写,把大致步 ...
- Paper | A Pseudo-Blind Convolutional Neural Network for the Reduction of Compression Artifacts
目录 非盲增强网络结构 训练目标 压缩系数预测子网络 网络结构 根据块QP判决结果得到帧QP预测结果 保持时序连续性 实验 发表在2019年TCSVT. 本文提出了一个兼具 预测压缩系数 和 非盲去压 ...
- 小白专场-FileTransfer-python语言实现
目录 更新.更全的<数据结构与算法>的更新网站,更有python.go.人工智能教学等着你:https://www.cnblogs.com/nickchen121/p/11407287.h ...
- 数据分析常用的Excel函数
Excel是我们工作中经常使用的一种工具,对于数据分析来说,这也是处理数据最基础的工具. 本文对数据分析需要用到的函数做了分类,并且有详细的例子说明,文章已做了书签处理,点击可跳转至相应位置. 函数分 ...
- Eureka服务注册中心错误:com.sun.jersey.api.client.ClientHandlerException: java.net.ConnectException: Connection refused: connect
报错信息 14:43:45.484 [main] INFO com.netflix.discovery.DiscoveryClient - Getting all instance registry ...
- mysql-5.7.23-winx64 解压版详细安装教程
1.下载解压版: 2.配置环境变量 (1)新建MYSQL_HOME变量,并配置值为: C:\softwaretool\mysql-5.7.23-winx64 计算机→属性→高级系统设置→高级→环境变量 ...
- Gevent工作原理(转)
作者:大U哥链接:https://www.zhihu.com/question/20703476/answer/15911452来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...