CF512E Fox And Polygon

CF512E Fox And Polygon

分析题意,我们首先需要知道这样一个性质:图形的任意两种状态之间是可以相互转换的。
也就是说,没有哪种状态是初始状态不能变化到的;同理,也没有哪种状态是终止状态不能变化到的。
此外我们还可以发现,变化步骤是可以倒推的。
结合以上几点,就可以得到这道题的做法了。
首先我们需要找到一个中间状态,为了方便,我们将这个中间状态定为所有点联向$1$号点的情况。
然后我们分别求出由初始状态变化为中间状态,和由终止状态变化为中间状态的步骤。
这个找步骤的过程如下:
枚举每个点,在这个点的左右两边分别找到一个与$1$点相连的点。根据分法(划分为数个三角形)可知,这两个点必然相连。然后删去这两点间的这条对角线并存储步骤即可。
这里需要注意的是,新出现的对角线并不一定是$1$号点和当前枚举点的连线,所以要枚举找出这个同时与被删去对角线两端点相连的点。
再这样一次操作后,当前枚举点不一定就会与$1$号点相连,所以要循环直到$1$号点和当前点相连为止,再枚举下一个点。
用同样的方法找到由终止状态到中间状态的变化过程。注意存储的步骤是新出现对角线的两个端点
最后输出所有步骤即可,其中由终止状态变化到中间状态的步骤需要倒序输出。
(但是我现在还没证明步骤数必定在$20000$之内,所以记录步骤用vector会更好)

#include<bits/stdc++.h>
#define N 1010

using namespace std;

int n,cnt1,cnt2;
bool edge1[N][N],edge2[N][N];

struct node {
	int frm,to;
}op1[20010],op2[20010];

void Read() {
	scanf("%d",&n);
	for(int i=1;i<=n-3;i++) {
		int u,v;
		scanf("%d%d",&u,&v);
		edge1[u][v]=1;
		edge1[v][u]=1;
	}
	for(int i=1;i<=n-3;i++) {
		int u,v;
		scanf("%d%d",&u,&v);
		edge2[u][v]=1;
		edge2[v][u]=1;
	}
	return;
}

void Solve() {
	for(int i=1;i<=n;i++) {
		edge1[i][i%n+1]=1;
		edge1[i%n+1][i]=1;
		edge2[i][i%n+1]=1;
		edge2[i%n+1][i]=1;
	}

	for(int i=2;i<=n;i++) {
		while(!edge1[1][i]) {
			int su=i-1,sv,eu=0,ev; //su=i-1:i的上一个点必与1点相连 su-sv -> es-ev
			for(int j=i+1;j<=n;j++) {
				if(edge1[1][j]) {
					sv=j;
					break;
				}
			}
			for(int k=1;k<=n;k++) {
				if(edge1[su][k]&&edge1[sv][k]) {
					if(eu==0) {
						eu=k;
					}
					else {
						ev=k;
						break;
					}
				}
			}
			edge1[su][sv]=0;
			edge1[sv][su]=0;
			edge1[eu][ev]=1;
			edge1[ev][eu]=1;
			op1[++cnt1]=(node){su,sv};
			//printf("op:%d %d %d %d i:%d\n",su,sv,eu,ev,i);
		}
	}
	for(int i=2;i<=n;i++) {
		while(!edge2[1][i]) {
			int su=i-1,sv,eu=0,ev; //su=i-1:i的上一个点必与1点相连 su-sv -> es-ev
			for(int j=i+1;j<=n;j++) {
				if(edge2[1][j]) {
					sv=j;
					break;
				}
			}
			for(int k=1;k<=n;k++) {
				if(edge2[su][k]&&edge2[sv][k]) {
					if(eu==0) {
						eu=k;
					}
					else {
						ev=k;
						break;
					}
				}
			}
			edge2[su][sv]=0;
			edge2[sv][su]=0;
			edge2[eu][ev]=1;
			edge2[ev][eu]=1;
			op2[++cnt2]=(node){eu,ev};
			//printf("op:%d %d %d %d i:%d\n",su,sv,eu,ev,i);
		}
	}

	return;
}

void Print() {
	printf("%d\n",cnt1+cnt2);
	for(int i=1;i<=cnt1;i++) {
		printf("%d %d\n",op1[i].frm,op1[i].to);
	}
	for(int i=cnt2;i>=1;i--) {
		printf("%d %d\n",op2[i].frm,op2[i].to);
	}
	return;
}

int main()
{
	Read();
	Solve();
	Print();
	return 0;
}
posted @ 2020-01-14 23:17  WalkerV  阅读(266)  评论(0编辑  收藏  举报