Escape【2019 CCPC 秦皇岛 E】【最大流】

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_41730082/article/details/102513841

HDU 6735


Problem Description

Given a maze of size n×m. The rows are numbered 1, 2, · · · , n from top to bottom while the columns are numbered 1, 2, · · · , m from left to right, which means that (1, 1) is the top-left corner and that (n, m) is the bottom-right corner. And for each cell of size 1 × 1, it is either blank or blocked.
There are a robots above the maze. For i-th robot, it is initially positioned exactly above the cell (1, pi), which can be described as (0, pi). And the initial moving direction of the robots are all downward, which can be written as (1, 0) in the vector form.
Also, there are b exits below the maze. For i-th exit, it is positioned exactly below the cell (n, ei), which can be described as (n + 1, ei).
Now, you want to let the robots escape from the maze by reaching one of the exits. However, the robots are only able to go straight along their moving directions and can’t make a turn. So you should set some turning devices on some blank cells in the maze to help the robots make turns.
There are 4 types of turning devices:

  • “NE-devices” : make the robots coming from above go rightward, and make the robots coming from right go upward. Coming from left or below is illegal.
  • “NW-devices” : make the robots coming from above go leftward, and make the robots coming from left go upward. Coming from right or below is illegal.
  • “SE-devices” : make the robots coming from below go rightward, and make the robots coming from right go downward. Coming from left or above is illegal.
  • “SW-devices” : make the robots coming from below go leftward, and make the robots coming from left go downward. Coming from right or above is illegal.
  • For each cell, the number of turning devices on it can not exceed 1. And collisions between the robots are ignored, which allows multiple robots to visit one same cell even at the same time.
    You want to know if there exists some schemes to set turning devices so that all the a robots can reach one of the b exits after making a finite number of moves without passing a blocked cell or passing a turning device illegally or going out of boundary(except the initial position and the exit).
    If the answer is yes, print “Yes” in a single line, or print “No” if the answer is no.

Input

The first line contains one positive integer T (1 ≤ T ≤ 10), denoting the number of test cases.
For each test case:
The first line contains four positive integers n, m, a, b (1 ≤ n, m ≤ 100, 1 ≤ a, b ≤ m), denoting the number of rows and the number of columns in the maze, the number of robots and the number of exits respectively.
Next n lines each contains a string of length m containing only “0” or “1”, denoting the initial maze, where cell (i, j) is blank if the j-th character in i-th string is “0”, while cell (i, j) is blocked if the j-th character in i-th string is “1”.
The next line contains a integers pi (1 ≤ pi ≤ m), denoting the initial positions (0, pi) of the robots.
The next line contains b integers ei (1 ≤ ei ≤ m), denoting the positions (n + 1, ei) of the exits.
It is guaranteed that all pis are pairwise distinct and that all eis are also pairwise distinct.

Output

Output T lines each contains a string “Yes” or “No”, denoting the answer to corresponding test case.


  题意是真的毒,我一开始把“illega”理解成了忽视的意思,但是实际上是非法的;一开始看到那个"not exceed 1"以为是每个变向器只能使用一次,但是实际上是每个点可以使用且仅使用一次。

  然后,这里有个隐藏的条件,可以推一下,每个点(x, y)的水平和竖直方向各自只会被经过最多一次。所以,在这里我们可以对水平和竖直分别拆点,并且流为1。然后,如果我们加了变向器,那么此时就会是的竖直方向和水平方向允许通过的方向是固定的,如何固定?我们让水平拆点链接上竖直方向上的拆点即可。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&( -x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define efs 1e-7
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define MP(a, b) make_pair(a, b)
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 107, maxP = 4e4 + 7, maxE = 2e5 + 7;
int N, M, A, B, S, T, area;
inline int _id(int x, int y) { return (x - 1) * M + y; }
char mp[maxN][maxN];
int head[maxP], cnt;
inline bool In_Map(int x, int y) { return x > 0 && y > 0 && x <= N && y <= M && mp[x][y] ^ '1'; }
struct Eddge
{
    int nex, to, flow;
    Eddge(int a=-1, int b=0, int c=0):nex(a), to(b), flow(c) {}
}edge[maxE];
inline void addEddge(int u, int v, int f)
{
    edge[cnt] = Eddge(head[u], v, f);
    head[u] = cnt++;
}
inline void _add(int u, int v, int f) { addEddge(u, v, f); addEddge(v, u, f); }
int deep[maxP], flow[maxP], cur[maxP];
inline bool bfs()
{
    for(int i=S; i<=T; i++) deep[i] = 0;
    queue<int> Q;
    Q.push(S); flow[S] = INF; deep[S] = 1;
    while(!Q.empty())
    {
        int u = Q.front(); Q.pop();
        for(int i=head[u], v, f; ~i; i=edge[i].nex)
        {
            v = edge[i].to; f = edge[i].flow;
            if(f && !deep[v])
            {
                deep[v] = deep[u] + 1;
                flow[v] = min(f, flow[u]);
                Q.push(v);
            }
        }
    }
    return deep[T];
}
int dfs(int u, int dist)
{
    if(u == T) return dist;
    for(int &i=cur[u], v, f; ~i; i=edge[i].nex)
    {
        v = edge[i].to; f = edge[i].flow;
        if(f && deep[v] == deep[u] + 1)
        {
            int di = dfs(v, min(dist, f));
            if(di)
            {
                edge[i].flow -= di;
                edge[i ^ 1].flow += di;
                return di;
            }
        }
    }
    return 0;
}
inline int Dinic()
{
    int ans = 0, tmp;
    while(bfs())
    {
        for(int i=S; i<=T; i++) cur[i] = head[i];
        while((tmp = dfs(S, INF))) ans += tmp;
    }
    return ans;
}
inline void init()
{
    cnt = 0; area = N * M; S = 0; T = 4 * area + 1;
    for(int i=S; i<=T; i++) head[i] = -1;
}
int main()
{
    int Cas; scanf("%d", &Cas);
    while(Cas--)
    {
        scanf("%d%d%d%d", &N, &M, &A, &B);
        init();
        for(int i=1; i<=N; i++) scanf("%s", mp[i] + 1);
        for(int i=1, id, up, dw, le, ri; i<=N; i++)
        {
            for(int j=1; j<=M; j++)
            {
                if(!In_Map(i, j)) continue;
                id = _id(i, j);
                _add(id, id + area, 1);
//                _add(id + area, id, 1);
                _add(id + 2 * area, id + 3 * area, 1);
//                _add(id + 3 * area, id + 2 * area, 1);
//                if(In_Map(i - 1, j))
//                {
//                    up = _id(i - 1, j);
//                    _add(id, up + area, 1);
//                }
                if(In_Map(i + 1, j))
                {
                    dw = _id(i + 1, j);
                    _add(id + area, dw, 1);
                }
//                if(In_Map(i, j - 1))
//                {
//                    le = _id(i, j - 1);
//                    _add(id + 2 * area, le + 3 * area, 1);
//                }
                if(In_Map(i, j + 1))
                {
                    ri = _id(i, j + 1);
                    _add(id + 3 * area, ri + 2 * area, 1);
                }
                _add(id + area, id + 2 * area, 1);
//                _add(id + 2 * area, id + area, 1);
                _add(id + 3 * area, id, 1);
//                _add(id, id + 3 * area, 1);
            }
        }
        for(int i=1, pos; i<=A; i++)
        {
            scanf("%d", &pos);
            _add(S, pos, 1);
        }
        for(int i=1, pos; i<=B; i++)
        {
            scanf("%d", &pos);
            _add(_id(N, pos) + area, T, 1);
        }
        printf(Dinic() == A ? "Yes\n" : "No\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41730082/article/details/102513841
今日推荐