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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章