• BZOJ2437 [Noi2011]兔兔与蛋蛋 【博弈论 + 二分图匹配】


    题目链接

    BZOJ2437

    题解

    JSOI2014很像
    只不过这题动态删点

    如果我们把空位置看做(X)的话,就会发现我们走的路径是一个(OX)交错的路径
    然后将图二分染色,当前点必胜,当且仅当当前点必须作为最大匹配的匹配点
    移动相当于删点,删点的话只需打个标记即可
    判断当前点是不是必选,只需尝试更改当前点匹配点的匹配点即可

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<map>
    #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define mp(a,b) make_pair<int,int>(a,b)
    #define cls(s) memset(s,0,sizeof(s))
    #define cp pair<int,int>
    #define LL long long int
    using namespace std;
    const int maxn = 1605,maxm = 100005,INF = 1000000000;
    inline int read(){
    	int out = 0,flag = 1; char c = getchar();
    	while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
    	while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
    	return out * flag;
    }
    int h[maxn],ne = 1;
    struct EDGE{int to,nxt;}ed[maxm];
    inline void build(int u,int v){
    	ed[++ne] = (EDGE){v,h[u]}; h[u] = ne;
    	ed[++ne] = (EDGE){u,h[v]}; h[v] = ne;
    }
    char s[45][45];
    int X[4] = {0,0,-1,1},Y[4] = {-1,1,0,0};
    int lk[maxn],vis[maxn],N,M,sx,sy,n;
    int id[45][45],px[maxn],py[maxn],c[maxn],Out[maxn];
    int win[maxn],ans[maxn],ansi;
    int bd[maxn][maxn];
    void dfs(int x,int y,int co){
    	id[x][y] = ++n; px[n] = x; py[n] = y; c[n] = co;
    	int nx,ny;
    	for (int k = 0; k < 4; k++){
    		nx = x + X[k];
    		ny = y + Y[k];
    		if (nx < 1 || ny < 1 || nx > N || ny > M || s[nx][ny] == s[x][y])
    			continue;
    		if (id[nx][ny]){
    			if (!bd[id[nx][ny]][id[x][y]]) build(id[x][y],id[nx][ny]);
    			bd[id[nx][ny]][id[x][y]] = bd[id[x][y]][id[nx][ny]] = true;
    		}
    		else {
    			dfs(nx,ny,co ^ 1);
    			if (!bd[id[nx][ny]][id[x][y]]) build(id[x][y],id[nx][ny]);
    			bd[id[nx][ny]][id[x][y]] = bd[id[x][y]][id[nx][ny]] = true;
    		}
    	}
    }
    bool find(int u){
    	Redge(u) if (!vis[to = ed[k].to] && !Out[to]){
    		vis[to] = true;
    		if (!lk[to] || find(lk[to])){
    			lk[to] = u; lk[u] = to;
    			return true;
    		}
    	}
    	return false;
    }
    int main(){
    	N = read(); M = read();
    	REP(i,N) scanf("%s",s[i] + 1);
    	REP(i,N) REP(j,M) if (s[i][j] == '.'){sx = i,sy = j,s[i][j] = 'X';break;}
    	dfs(sx,sy,0);
    	int K = read() << 1,x,y,nx = sx,ny = sy,u;
    	REP(i,n) if (!c[i]) cls(vis),find(i);
    	REP(i,K){
    		cls(vis);
    		x = read(); y = read();
    		Out[u = id[nx][ny]] = true;
    		if (lk[u]){
    			win[i] = !find(lk[u]);
    			if (win[i]) lk[lk[u]] = 0;
    		}
    		else win[i] = 0;
    		lk[u] = 0;
    		nx = x; ny = y;
    	}
    	win[K] = true;
    	for (int i = 1; i <= K; i += 2)
    		if (win[i] && win[i + 1]) ans[++ansi] = (i + 1) >> 1;
    	printf("%d
    ",ansi);
    	REP(i,ansi) printf("%d
    ",ans[i]);
    	return 0;
    }
    
    
  • 相关阅读:
    内置函数filter()和匿名函数lambda解析
    time&datetime模块详解
    python学习笔记:*args和**kwargs使用原理?
    python学习笔记:深浅拷贝的使用和原理
    python传参是传值还是传引用
    第215天:Angular---指令
    第214天:Angular 基础概念
    第213天:12个HTML和CSS必须知道的重点难点问题
    第212天:15种CSS居中的方式,最全了
    第211天:git和github的区别和使用详解
  • 原文地址:https://www.cnblogs.com/Mychael/p/9251088.html
Copyright © 2020-2023  润新知