CF Gym102411C Cross-Stitch

gym

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;
}
posted @ 2020-05-05 14:14  ✡smy✡  阅读(172)  评论(0编辑  收藏  举报