传送门

题意:

给出一个\(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

最新文章

  1. 基于.NET平台常用的框架整理(转)
  2. 什么是P3O?
  3. JS-Date对象
  4. Windows Server 2008R2配置MySQL Cluster
  5. javascript优化--08模式(代码复用)01
  6. Redis学习手册(List数据类型)
  7. docker &amp; nodejs &amp; mongodb
  8. WP8.1和Win8.1的不同之处
  9. node begining
  10. IIS与ASP.NET 通信机制深度剖析
  11. 基于visual Studio2013解决C语言竞赛题之1050矩阵反斜线求和
  12. Netty开发redis客户端,Netty发送redis命令,netty解析redis消息
  13. 解决Idea GitLab Clone failed: Authentication failed for的问题
  14. 手动安装composer详细教学
  15. extend 与 append 的区别
  16. muduo网络库学习笔记(五) 链接器Connector与监听器Acceptor
  17. ReentrantReadWriteLock分析
  18. Java(Android)线程池[转]
  19. ORACLE数据泵还原(IMPDP命令)
  20. 700. Search in a Binary Search Tree

热门文章

  1. Jmeter之BeanShell
  2. MySQL学习笔记6——备份与恢复
  3. layer icon样式及 一些弹框使用方法
  4. MySQL实战45讲学习笔记:第三十五讲
  5. 修改官方发行openstack镜像的cloud-init登录方式为账号密码登录
  6. 能耗监测平台GPRS通讯服务器的架构设计
  7. 奥展项目笔记07--vue绑定下拉框和checkbox总结
  8. 自己搭建 NuGet.Server 环境
  9. 【Easyexcel】java导入导出超大数据量的xlsx文件 解决方法
  10. NRF24L01双向无线通信