之前看了下二分图博弈,觉得理解了
这道板子题,我居然又困惑了好久!!真想抽自己~
明显看出这是一张二分图,我们用 的奇偶性分类
接下来就可以套二分图博弈的板子了
(注意,下面是把先选择第一步棋子放哪里的人认为是先手,也就是Alice)
#include <bits/stdc++.h>
using namespace std;
#define id(x,y) (x-1)*m+y
const int maxn=2e5+10;
const int inf=1e9;
int n,m,s,t,yin[maxn];
int dis[maxn];
char a[109][109];
struct edge{
int to,nxt,flow;
}d[maxn]; int head[maxn],cnt=1;
void add(int u,int v,int flow){
d[++cnt]=(edge){v,head[u],flow},head[u]=cnt;
d[++cnt]=(edge){u,head[v],0},head[v]=cnt;
}
bool bfs(int s,int t)
{
memset(dis,0,sizeof(dis));
dis[s]=1;
queue<int>q; q.push( s );
while( !q.empty() )
{
int u=q.front(); q.pop();
for(int i=head[u];i;i=d[i].nxt )
{
int v=d[i].to;
if( d[i].flow&&dis[v]==0 )
{
dis[v]=dis[u]+1;
if( v==t ) return true;
q.push( v );
}
}
}
return false;
}
int dinic(int u,int t,int flow)
{
if( u==t ) return flow;
int res=flow;
for(int i=head[u];i&&res;i=d[i].nxt )
{
int v=d[i].to;
if( dis[v]==dis[u]+1&&d[i].flow)
{
int temp=dinic(v,t,min(res,d[i].flow) );
if( temp==0 ) dis[v]=0;
res-=temp;
d[i].flow-=temp;
d[i^1].flow+=temp;
}
}
return flow-res;
}
typedef pair<int,int>p;
vector<p>vec;
int main()
{
cin >> n >> m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin >> a[i][j];
s=0,t=n*m+1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if( a[i][j]=='#' ) continue;
if( (i+j)&1 ) add(s,id(i,j),1);
else add(id(i,j),t,1);
yin[id(i,j)]=cnt-1;
if( i>1&&a[i-1][j]=='.' )
{
if( (i+j)&1 ) add(id(i,j),id(i-1,j),1);
else add(id(i-1,j),id(i,j),1);
}
if( j>1&&a[i][j-1]=='.' )
{
if( (i+j)&1 ) add(id(i,j),id(i,j-1),1);
else add(id(i,j-1),id(i,j),1);
}
}
int ans=0;
while( bfs(s,t) ) ans+=dinic(s,t,inf);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if( a[i][j]=='#' ) continue;
if( (i+j)&1 )
{
if( dis[id(i,j)]==0&&d[yin[id(i,j)]].flow==0 ) continue;//在最大匹配的充要条件
else vec.push_back(p(i,j));//只要有可能不在最大匹配,就可以赢
}
}
for(int i=2;i<=cnt;i+=2)
d[i^1].flow+=d[i].flow,d[i].flow=0;
while( bfs(t,s) ) ans+=dinic(t,s,inf);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if( a[i][j]=='#' ) continue;
if( (i+j)&1 ) continue;
else
{
if( dis[id(i,j)]==0&&d[yin[id(i,j)]+1].flow==0 ) continue;//在最大匹配的充要条件
else vec.push_back(p(i,j));//只要有可能不在最大匹配,就可以赢
}
}
cout << vec.size() << endl;
sort(vec.begin(),vec.end());
for(int i=0;i<vec.size();i++)
cout << vec[i].first << " " << vec[i].second << '\n';
}