思路:每一个点分成四个方向,然后由于一个点可以转一个方向,设置一个中转站,入点和出点之间设置一个容量为1的边,要转弯就先进入这个中转站,再转入这个点的其他方向。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; const int maxn = 2e5; const int maxm = 2 * maxn; const int inf = 0x3f3f3f3f; int n, m, S, T, in, ou; char mp[110][110]; int h[maxn], tot, e[maxm], f[maxm], ne[maxm]; int q[maxn], d[maxn], cur[maxn]; int get(int x, int y) { return (x - 1) * m + y; } void add(int u, int v) { e[tot] = v; f[tot] = 1; ne[tot] = h[u]; h[u] = tot ++ ; e[tot] = u; f[tot] = 0; ne[tot] = h[v]; h[v] = tot ++ ; } bool bfs() { int hh = 0, tt = -1; memset(d, -1, sizeof d); cur[S] = h[S]; d[S] = 0; q[++tt] = S; while (hh <= tt) { int u = q[hh++]; for (int i = h[u]; ~i; i = ne[i]) { int v = e[i]; if (f[i] && d[v] == -1) { d[v] = d[u] + 1; cur[v] = h[v]; if (v == T) return true; q[++tt] = v; } } } return false; } int dfs(int u, int limit) { if (u == T) return limit; int flow = 0; for (int i = cur[u]; ~i && flow < limit; i = ne[i]) { int v = e[i]; if (d[v] == d[u] + 1 && f[i]) { int t = dfs(v, min(f[i], limit - flow)); if (!t) d[v] = -1; flow += t; f[i] -= t; f[i ^ 1] += t; } } return flow; } int dinic() { int r = 0, flow; while (bfs()) { while (flow = dfs(S, inf)) r += flow; } return r; } int main () { int cas; scanf("%d", &cas); while (cas--) { scanf("%d %d %d %d", &n, &m, &in, &ou); // printf("in=%d ", in); for (int i = 1; i <= n; i ++ ) scanf("%s", mp[i]+1); S = maxn - 2; T = maxn - 1; memset(h, -1, sizeof h); tot = 0; for (int i = 1; i <= n; i ++ ) { for (int j = 1; j <= m; j ++ ) { if (mp[i][j] == '1') continue; if (mp[i+1][j] == '0') add(0 * n * m + get(i, j), 0 * n * m + get(i+1, j)); if (mp[i][j-1] == '0') add(1 * n * m + get(i, j), 1 * n * m + get(i, j-1)); if (mp[i-1][j] == '0') add(2 * n * m + get(i, j), 2 * n * m + get(i-1, j)); if (mp[i][j+1] == '0') add(3 * n * m + get(i, j), 3 * n * m + get(i, j+1)); add(0 * n * m + get(i, j), 4 * n * m + get(i, j)); add(1 * n * m + get(i, j), 4 * n * m + get(i, j)); add(2 * n * m + get(i, j), 4 * n * m + get(i, j)); add(3 * n * m + get(i, j), 4 * n * m + get(i, j)); add(4 * n * m + get(i, j), 5 * n * m + get(i, j)); add(5 * n * m + get(i, j), 0 * n * m + get(i, j)); add(5 * n * m + get(i, j), 1 * n * m + get(i, j)); add(5 * n * m + get(i, j), 2 * n * m + get(i, j)); add(5 * n * m + get(i, j), 3 * n * m + get(i, j)); } } for (int i = 0; i < in; i ++ ) { int id; scanf("%d", &id); add(S, get(1, id)); } for (int i = 0; i < ou; i ++ ) { int id; scanf("%d", &id); add(get(n, id), T); } int mxflow = dinic(); // printf("mxflow = %d in=%d ", mxflow, in); if (mxflow >= in) puts("Yes"); else puts("No"); } return 0; }