Solution
由于是博弈论,可以转化成求二分图的关键点,即必然在二分图匹配中出现的点
算法要考虑染色,即当前点染黑,周围点染白,染色后把连通块都用算法匹配掉
若Alice走不在最大匹配点集内的点,则该点的周围连的一定都是匹配点,可知Bob一定走一条非匹配边到一个匹配点
由于只要先选了最大匹配点就必胜,因此在这个条件下Alice必胜
最后统计一下答案就好了
#include <stdio.h> #include <string.h> template<class T> inline void read(T &x) { int c=getchar();bool b=0; for(x=0;c<48||c>57;c=getchar())if(c==45)b=1; for(;c>47&&c<58;c=getchar())x=(x<<1)+(x<<3)+c-48; if(b)x=-x; } const int N=200; bool win[N*N]; int color[N*N],n,m,lab,num[N][N],vind,vis[N*N],lnk[N*N],Ans,fir[N*N],et=-1; char mat[N][N]; struct Position { int x,y; }pos[N*N]; struct Pointer { int v,next; }e[N*N*5]; inline void link(int x,int y) { e[++et]=(Pointer){y,fir[x]},fir[x]=et; e[++et]=(Pointer){x,fir[y]},fir[y]=et; } bool dfs(int at) { for(int j=fir[at];~j;j=e[j].next) if(vis[e[j].v]!=vind) { vis[e[j].v]=vind; if((!lnk[e[j].v]) || dfs(lnk[e[j].v])) { lnk[e[j].v]=at; return 1; } } return 0; } void find(int at) { for(int j=fir[at];~j;j=e[j].next) if(lnk[e[j].v] && (!win[lnk[e[j].v]])) { win[lnk[e[j].v]]=1; find(lnk[e[j].v]); } } int main() { memset(fir,-1,sizeof fir); read(n),read(m); for(int i=1;i<=n;i++) scanf("%s",mat[i]+1); lab=0; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(mat[i][j]=='.') { num[i][j]=++lab; pos[lab].x=i; pos[lab].y=j; color[lab]=((i+j)&1); if(i>1 && mat[i-1][j]=='.') link(lab,num[i-1][j]); if(j>1 && mat[i][j-1]=='.') link(lab,num[i][j-1]); } for(int i=1;i<=lab;i++) if(!color[i]) { ++vind; dfs(i); } for(int i=1;i<=lab;i++) if(color[i]&&lnk[i]) lnk[lnk[i]]=i; for(int i=1;i<=lab;i++) if(!lnk[i]) { win[i]=1; find(i); } Ans=0; for(int i=1;i<=lab;i++) Ans+=win[i]; printf("%d ",Ans); for(int i=1;i<=lab;i++) if(win[i]) printf("%d %d ",pos[i].x,pos[i].y); return 0; }