[BZOJ2437] [Noi2011] Egg and rabbit (Game + bipartite graph)

Portal

Meaning of the questions:
given a (n * m \) \ board, there are a number of black pawn above, a number of white pieces, there is a space.
Each time the upper hand select a space, it will be exchanged with an adjacent one white pawn; FLAC select a space, and adjacent to a black pawn exchange.
The final movement of people can not lose.

And now gives a board game, the end result is losing the upper hand. You just get the output of mistakes and several times that number of times in this game.

Ideas:

  • First clear upper hand mistake: if and only if there is a winning strategy before its operations, flac winning strategy after its operation.
  • Then consider the two operations, which is equivalent to moving the box, only the upper hand toward the white point, black point moves only flip. But so consider issues that may arise because the actual process, the position of the black point and white point will change, but may in fact prove: not through a grid twice. In this case the mobile space directly correctness is assured.

Proofs to consider a case found to be smaller to form a ring, and the number of rows or number of columns plus one plus an even number of lattice a change does not affect.

  • The question then transformed into: starting from a fixed black spots, black and white form a path, if there is a winning strategy in the path at some point.
  • If there is a point winning strategy, then it is certainly only from the odd step to take, it is observed that a bipartite graph, that is to say, in a bipartite graph, for example, starting from the left, we can only stay in the right; that is, the point of departure must be left at a point of maximum matching, because the stay means that there is another matching scheme on the left.
  • The problem is further transformed into: a bipartite graph is given, it is determined whether a certain point in the corresponding bipartite graph. This will then direct node and edge tear down the violence in Hungary on the line.

Ideas and game this question is somewhat similar, but a little bit different.
Pay attention to, because we can not pass a point twice in the same, that is to say if the current through this point, can not go back to this point when looking for augmenting paths. Otherwise, the idea of it contradictory.
See details Code:

/*
 * Author:  heyuhhh
 * Created Time:  2019/11/7 10:52:33
 */
#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 INF 0x3f3f3f3f
#define Local
#ifdef Local
  #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  void err() { std::cout << '\n'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 45, M = 2605;

int n, m;
char s[N];
int mp[N][N];
vector <int> g[M];

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] == 0;
}

int T;
int match[M], vis[M], ban[M];
bool win[M];

bool dfs(int x) {
    if(ban[x]) return false;   
    for(int i = 0; i < sz(g[x]); i++){
        int it = g[x][i];
        if(vis[it] != T && !ban[it]) {
            vis[it] = T;
            if(match[it] == -1 || dfs(match[it])) {
                match[it] = x;
                match[x] = it;
                return true;
            }
        }   
    }
    return false;
}

void run(){
    cin >> n >> m;
    int X, Y;
    for(int i = 1; i <= n; i++) {
        cin >> (s + 1);
        for(int j = 1; j <= m; j++) {
            if(s[j] == 'X') mp[i][j] = 1;
            else if(s[j] == 'O') mp[i][j] = 0;
            else mp[i][j] = 1, X = i, Y = j;
        }
    }
    static int dx[4] = {-1, 1, 0, 0}, dy[4] = {0, 0, -1, 1};
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= m; j++) if(mp[i][j]) {
            for(int k = 0; k < 4; k++) {
                int nx = i + dx[k], ny = j + dy[k];
                if(ok(nx, ny)) {
                    g[id(i, j)].push_back(id(nx, ny));
                    g[id(nx, ny)].push_back(id(i, j));
                }
            }
        }
    }
    memset(match, -1, sizeof(match));
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= m; j++) if(mp[i][j]) {
            ++T; dfs(id(i, j));
        }
    }
    int k; cin >> k;
    for(int i = 1; i <= k + k; i++) {
        ban[id(X, Y)] = true;
        if(match[id(X, Y)] != -1) {
            int nw = match[id(X, Y)];
            match[id(X, Y)] = match[nw] = -1;
            ++T;
            win[i] = !dfs(nw);
        }   
        cin >> X >> Y;
    }
    vector <int> res;
    for(int i = 1; i <= k; i++) {
        if(win[2 * i - 1] && win[2 * i]) res.push_back(i);
    }
    cout << sz(res) << '\n';
    for(int i = 0; i < sz(res); i++) cout << res[i] << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    run();
    return 0;
}

Guess you like

Origin www.cnblogs.com/heyuhhh/p/11811411.html