「雅礼集训 2017 Day2」棋盘游戏
SOL:
网络流神题,黑白染色比较显然吧。然后我们发现这是一个二分图匹配,大力胡一发,发现Alice走增广边,Bob走非增广边,那么当有完美匹配Alice就必胜了。
但是我们发现对每一个点做一次最大流复杂度不科学,我们先随便找一个点,去找增广路就好了。
#include<bits/stdc++.h> #define f(x) G.fall[G.head[x]] #define exo(x) for(int i=head[x];i;i=net[i]) #define Exo(x) for(int& i=hea[x];i;i=net[i]) #define vv fall[i] #define v G.fall[i] #define eho(x) for(int i=G.head[x];i;i=G.net[i]) #define ha(x,y) ((x)*101+(y)) #define xh(x) x/101 #define yh(x) x%101 #define iha(i,j) (20000+ha(i,j)) #define N 120301 #define M 720301 #define inf (1<<29) using namespace std; int be,ed,in[N],n,m,p[2],S,T,x,que[N],idx; int id[105][105],co[105*105],col[105][105],ok[105*105],vis[105*105]; int mx[]={1,-1,0,0},my[]={0,0,1,-1}; char mp[107][107]; struct Node{ int tot,head[N],hea[N],net[M],fall[M],gap[N],SI,d[N],cost[M],que[N],s,t,x; Node() {tot=1;} inline void add(int x,int y,int co) { fall[++tot]=y; net[tot]=head[x]; head[x]=tot; cost[tot]=co; } inline void adds(int x,int y,int co=1) { add(x,y,co),add(y,x,0); } void bfs() { memset(gap,0,sizeof gap); memset(d,0,sizeof d); memcpy(hea,head,sizeof head); que[be=0,ed=1]=t; gap[d[t]=1]=1; while (be<ed) { x=que[++be]; exo(x) if (!d[vv]) que[++ed]=vv,gap[d[vv]=d[x]+1]++; } } int dfs(int x,int fl) { if (x==t) return fl; if (!fl) return 0; int tmp,flow=0; Exo(x) if (d[vv]+1==d[x]&& (tmp=dfs(vv,min(fl,cost[i])))) { fl-=tmp,flow+=tmp,cost[i]-=tmp,cost[i^1]+=tmp; if (!fl) return flow; } if (!(--gap[d[x]]))d[s]=SI; ++gap[++d[x]]; hea[x]=head[x]; return flow; } int isap(int S,int T,int SIZ){ s=S; t=T; SI=SIZ+1; bfs(); int flow=dfs(s,inf); while (d[s]<SI) flow+=dfs(s,inf); return flow; } }G; #define sight(x) ('0'<=x&&x<='9') inline void read(int &x){ static char c; for (c=getchar();!sight(c);c=getchar()); for (x=0;sight(c);c=getchar())x=x*10+c-48; } void write(int x){if (x<10) {putchar('0'+x); return;} write(x/10); putchar('0'+x%10);} inline void writeln(int x){ if (x<0) putchar('-'),x*=-1; write(x); putchar('\n'); } inline void writel(int x){ if (x<0) putchar('-'),x*=-1; write(x); putchar(' '); } inline void dfs0(int x){ vis[x]=1; if(co[x]==1) ok[x]=1; eho(x) if(!vis[v]&&G.cost[i]==1) dfs0(v); } inline void dfs1(int x){ vis[x]=1; if(co[x]==0) ok[x]=1; eho(x) if(!vis[v]&&G.cost[i^1]==1) dfs1(v); } signed main(){ // freopen("a.in","r",stdin); read(n); read(m); for(int i=1;i<=n;++i) scanf("%s",mp[i]+1); S=++idx,T=++idx; for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) { col[i][j]=(i+j)&1; if(mp[i][j]=='.') id[i][j]=++idx,co[idx]=col[i][j]; } for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) if(mp[i][j]!='#') { if(col[i][j]) G.adds(S,id[i][j]); else G.adds(id[i][j],T); if(col[i][j]) for(int k=0;k<4;++k) G.adds(id[i][j],id[i+mx[k]][j+my[k]]); } cerr<<G.isap(S,T,n*m+2)<<endl; dfs0(S); memset(vis,0,sizeof(vis)); dfs1(T); int ans=0; for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) if(id[i][j]) ans+=ok[id[i][j]]; writeln(ans); for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) if(ok[id[i][j]]) writel(i),writeln(j); }