設X
數量有\(a\)個.這裏的路徑最短長度也只能夠\(4a-1\),其中\(2a\)條正面邊和\(2a-1\)條反面邊交替連接.容易想到歐拉路,然後聯想到歐拉回路,所以如果可以構造一個歐拉回路,那麼去掉一條反面的邊即可得到答案
考慮把所有的X
的左上點左下點連邊,右上點右下點連邊,然後跑一個正反面交替的歐拉回路即可.至於爲什麼存在歐拉回路,考慮增量構造,每次往當前8連通塊加入一個X
.由於初始情況下(只有一個X
)存在歐拉回路,然後每次加一個X
,可以發現我們可以在這個新的X
和連通塊的焦點處交換兩個迴路的邊,即\((...\to E\to F\to ...)\)和\((A
\to B\to C\to D)\)改爲\((...\to E\to D\to A\to B\to C\to F\to ...)\),就可以得到一個新歐拉回路了!
#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\n",ta-2);
for(int i=2;i<=ta;++i) printf("%d %d\n",ps[an[i]][1],ps[an[i]][0]);
return 0;
}