zoukankan      html  css  js  c++  java
  • LOJ#6033. 「雅礼集训 2017 Day2」棋盘游戏 题解

    题目链接

    把每个非 '#' 的格子当成点,共用边的格子所代表的点之间连一条边,不难发现这是个二分图。

    不难发现这个二分图上的博弈,先手必胜当且仅当起始点一定会被包含在最大匹配中,否则后手只要一直走匹配边就赢了。

    那么我们判断每个点是否可以成为这样的起始点即可。

    求最大匹配的部分可以使用匈牙利算法也可以直接网络流,复杂度为 (Theta(n^2m^2))(Theta((nm)^{1.5}))

    code :

    #include <bits/stdc++.h>
    using namespace std;
    template <typename T> void read(T &x){
    	static char ch; x = 0,ch = getchar();
    	while (!isdigit(ch)) ch = getchar();
    	while (isdigit(ch)) x = x * 10 + ch - '0',ch = getchar();
    }
    inline void write(int x){if (x > 9) write(x/10); putchar(x%10+'0'); }
    inline int Get(){
    	static char ch; ch = getchar();
    	while (ch != '.' && ch != '#') ch = getchar();
    	return ch == '.' ? 1 : 0;
    }
    const int N = 105,V = N * N;
    int n,m,mp[N][N],id[N][N],cntv; 
    int G[V][4],deg[V];
    inline void add(int x,int y){ G[x][deg[x]++] = y; G[y][deg[y]++] = x; }
    int match[V]; bool vis[V];
    inline bool dfs(int x){
    	if (vis[x]) return 0; vis[x] = 1;
    	for (int y,i = 0; i < deg[x]; ++i)
    		if (!match[y=G[x][i]] || dfs(match[y])){ match[y] = x,match[x] = y; return 1; }
    	return 0;
    }
    inline void dfs_ans(int x){
    	if (vis[x]) return; vis[x] = 1;
    	for (int y,i = 0; i < deg[x]; ++i) if (match[y=G[x][i]]) dfs_ans(match[y]);
    }
    int main(){
    	int i,j;
    	read(n),read(m);
    	for (i = 1; i <= n; ++i) for (j = 1; j <= m; ++j) if (mp[i][j] = Get()) id[i][j] = ++cntv;
    	for (i = 1; i <= n; ++i) for (j = 1; j <= m; ++j) if (mp[i][j] && ((i+j)&1)){
    		if (id[i-1][j]) add(id[i][j],id[i-1][j]);
    		if (id[i+1][j]) add(id[i][j],id[i+1][j]);
    		if (id[i][j-1]) add(id[i][j],id[i][j-1]);
    		if (id[i][j+1]) add(id[i][j],id[i][j+1]);
    	}
    	for (i = 1; i <= n; ++i) for (j = 1; j <= m; ++j) if (mp[i][j] && ((i+j)&1))
    		memset(vis,0,cntv+1),dfs(id[i][j]);
    	memset(vis,0,cntv+1);
    	for (i = 1; i <= cntv; ++i) if (!match[i]) dfs_ans(i);
    	int ans = 0;
    	for (i = 1; i <= n; ++i) for (j = 1; j <= m; ++j) if (id[i][j] && vis[id[i][j]]) ++ans;
    	write(ans),putchar('
    ');
    	for (i = 1; i <= n; ++i) for (j = 1; j <= m; ++j) if (id[i][j] && vis[id[i][j]]) write(i),putchar(' '),write(j),putchar('
    ');
    	return 0;
    }
    
  • 相关阅读:
    Spring aop 实现异常拦截
    drf 视图家族
    算法与数据结构
    接口
    Kubernetes
    drf
    drf 序列化
    drf 内部模块
    drf 接口
    vue
  • 原文地址:https://www.cnblogs.com/s-r-f/p/13756452.html
Copyright © 2011-2022 走看看