设X
数量有(a)个.这里的路径最短长度也只能够(4a-1),其中(2a)条正面边和(2a-1)条反面边交替连接.容易想到欧拉路,然后联想到欧拉回路,所以如果可以构造一个欧拉回路,那么去掉一条反面的边即可得到答案
考虑把所有的X
的左上点左下点连边,右上点右下点连边,然后跑一个正反面交替的欧拉回路即可.至于为什么存在欧拉回路,考虑增量构造,每次往当前8连通块加入一个X
.由于初始情况下(只有一个X
)存在欧拉回路,然后每次加一个X
,可以发现我们可以在这个新的X
和连通块的焦点处交换两个回路的边,即((... o E o F o ...))和((A
o B o C o D))改为((... o E o D o A o B o C o F o ...)),就可以得到一个新欧拉回路了!
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N=100+10,M=N*N;
int rd()
{
int x=0,w=1;char ch=0;
while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+(ch^48);ch=getchar();}
return x*w;
}
struct graph
{
int to[M<<3],nt[M<<3],hd[M],tot=1;
bool ban[M<<3];
void adde(int x,int y)
{
++tot,to[tot]=y,nt[tot]=hd[x],hd[x]=tot;
++tot,to[tot]=x,nt[tot]=hd[y],hd[y]=tot;
}
}g[2];
int n,m,id[N][N],ps[M][2],t,an[M<<3],ta;
char cc[N];
void dfs(int x,int o)
{
for(int &i=g[o].hd[x];i;i=g[o].nt[i])
{
if(g[o].ban[i]) continue;
g[o].ban[i]=g[o].ban[i^1]=1;
dfs(g[o].to[i],o^1);
}
an[++ta]=x;
}
int main()
{
m=rd(),n=rd();
for(int i=0;i<=n;++i)
for(int j=0;j<=m;++j)
id[i][j]=++t,ps[t][0]=i,ps[t][1]=j;
int sx=0;
for(int i=1;i<=n;++i)
{
scanf("%s",cc+1);
for(int j=1;j<=m;++j)
if(cc[j]=='X')
{
sx=id[i][j];
g[0].adde(id[i-1][j-1],id[i][j]),g[0].adde(id[i-1][j],id[i][j-1]);
g[1].adde(id[i-1][j-1],id[i][j-1]),g[1].adde(id[i-1][j],id[i][j]);
}
}
dfs(sx,0);
printf("%d
",ta-2);
for(int i=2;i<=ta;++i) printf("%d %d
",ps[an[i]][1],ps[an[i]][0]);
return 0;
}