2020.7.22 T2网格图游戏(jz暑假训练day7)

Description在这里插入图片描述

Input在这里插入图片描述

Output

在这里插入图片描述

Sample Input

3 4
2 1 E 1 2 N
2 1 N 1 1 N
3 1 N 2 1 N
2 2 N 1 1 N

Sample Output

YES
YES
NO
NO

赛时

暴力40分

正解

并查集,首先提一下这个题是强制在线啊,给你的两个路有一个是没有用的,看起来很绕,其实就是根据上一次的答案来确定这一次的查询。
然后呢我们先画个图,跟上面不一样,我们将点看成一个矩阵:
在这里插入图片描述

我们以样例的第一个查询为例,是2 1 E,也就是2,1和3,1这两个方块(红),之后题目说我们把这条边堵上,之后问是否联通。那联系到我们上面的图就是这两个方块之间的边被打破了。也就是黄色节点之间的边。之后根据上面的图,发现节点一共是(n+1)*(n+1)个。
之后我们就考虑算法了,首先对于一个进来的a1,b1,c1,我们可以知道它与它要去的另个方块,中间的边,的两边节点是多少,之后我们查询这两个节点是否在同一个集合,如果是也输出no,不是就是输出yes,之后如果不是一个集合就要记得合并。然后就这么做就行了。
最后是初始化问题了,当一个节点在边上的时候,它的父亲就是1,否则就是自己,还有不要傻乎乎的搞二维并查集,对于每个点i,j搞个编号就行了。之后,对于我们的图是按平面直角坐标系做的,而i,j两重循环去转移的话,i是枚举行,j是枚举列,所以也就是j是横坐标,i是纵坐标,这里不要搞反了。

#include<cstdio>
#define N 707
using namespace std;
int n,k,f[N*N],g[N][N],cnt;
bool bz;
int get(int x){return x==f[x]?x:f[x]=get(f[x]);}
bool find(int x,int y){
	int fx=get(x),fy=get(y);
	if(fx==fy) return 1;
	f[fx]=fy;//不同就合并
	return 0;
}
int main(){
	freopen("sox.in","r",stdin);
	freopen("sox.out","w",stdout);
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n+1;i++)
	for(int j=1;j<=n+1;j++){//初始化节点
		g[j][i]=++cnt;//记得是j在前i在后
		if(i==1||j==1||i==n+1||j==n+1) f[g[j][i]]=1;//在便便就是1
		else f[g[j][i]]=cnt;//自己
	}
	bz=1;//用来判断是第几个边被查询,1时就是第一条边,0时就是第二条边
	for(int i=1;i<=k;i++){
		int a1,b1,a2,b2,x,y;
		char c1,c2;
		scanf("%d %d %c %d %d %c",&a1,&b1,&c1,&a2,&b2,&c2);
		if(!bz) a1=a2,b1=b2,c1=c2;//当bz=0时,查询第二条边,那么就赋一下值给a1,b1,c1 这样方便
		if(c1=='E')
			x=g[a1+1][b1],y=g[a1+1][b1+1];//边的两边的节点
		else
			x=g[a1][b1+1],y=g[a1+1][b1+1];//同理
		bool b=find(x,y);//判断
		if(b)
			bz=0,printf("NO\n");
		else
			bz=1,printf("YES\n");
	}
}

猜你喜欢

转载自blog.csdn.net/jay_zai/article/details/107521072