ZOJ-4127 Grid with Arrows

题目描述:

BaoBao has just found a grid with n rows and m columns in his left pocket, where the cell in the j-th column of the i-th row (indicated by (i, j)) contains an arrow (pointing either upwards, downwards, leftwards or rightwards) and an integer a[i][j].

BaoBao decides to play a game with the grid. He will first select a cell as the initial cell and tick it. After ticking a cell (let's say BaoBao has just ticked cell (i, j)), BaoBao will go on ticking another cell according to the arrow and the integer in cell (i, j).

  • If the arrow in cell (i, j) points upwards, BaoBao will go on ticking cell (i−a[i][j],j) if it exists.
  • If the arrow in cell (i, j) points downwards, BaoBao will go on ticking cell (i+a[i][j],j) if it exists.
  • If the arrow in cell (i, j) points leftwards, BaoBao will go on ticking cell (i,j−a[i][j]) if it exists.
  • If the arrow in cell (i, j) points rightwards, BaoBao will go on ticking cell (i,j+a[i][j]) if it exists.

If the cell BaoBao decides to tick does not exist, or if the cell is already ticked, the game ends.

BaoBao is wondering if he can select a proper initial cell, so that he can tick every cell in the grid exactly once before the game ends. Please help him find the answer.

Input

There are multiple test cases. The first line contains an integer T, indicating the number of test cases. For each test case:

The first line contains two integers n and m (1≤n×m≤1e5), indicating the number of rows and columns of the grid.

For the following n lines, the i-th line contains a string s[i]​ consisting of lowercased English letters (∣s[i]​∣=m, s[i][j]∈{’u’ (ascii: 117),’d’ (ascii: 100),’l’ (ascii: 108),’r’ (ascii: 114)}), where s[i][j] indicates the direction of arrow in cell (i, j).

  • If s[i][j]=’u’, the arrow in cell (i, j) points upwards.
  • If s[i][j]=’d’, the arrow in cell (i, j) points downwards.
  • If s[i][j]=’l’, the arrow in cell (i, j) points leftwards.
  • If s[i][j]=’r’, the arrow in cell (i, j) points rightwards.

For the following nn lines, the ii-th line contains mm integers a[i][1]​,a[i][2],…,a[i][m] 1≤ai,j​≤max(n,m)), where a[i][j] indicates the integer in cell (i, j).

It's guaranteed that the sum of n×m of all test cases does not exceed 10^6.

Output

For each test case output one line. If BaoBao can find a proper initial cell, print "Yes" (without quotes), otherwise print "No" (without quotes).

Sample

Input

2
2 3
rdd
url
2 1 1
1 1 2
2 2
rr
rr
1 1
1 1

Output

Yes
No

Hint

For the first sample test case, BaoBao can select cell (1, 2) as the initial cell, so that he can tick all the cells exactly once in the following order: (1, 2), (2, 2), (2, 3), (2, 1), (1, 1), (1, 3).

For the second sample test case, BaoBao can only tick at most 2 cells no matter which cell is selected as the initial cell.

题目大意:给你一个n行m列的矩阵,对于矩阵中的点(i,j),给出了一个方向和一个值,由它们可以找到另一个点,问能否从某一个点开始,按照给定的方向和值走完所有的点。

思路分析:经过所有的点且每条边只经过一次,可以想到欧拉路径。题目可以转换为一个有向图,因此我们可以统计这个有向图中每一个点的入度和出度,若这个有向图中每一个点的入度都等于出度,则存在欧拉回路,满足;若存在一个点的入度比出度大1,存在一个点的出度比入度大1,其余的点入度出度相等,则也满足。注:在判断是否含有欧拉路径前要先判断有向图是否连通,只有连通图才有欧拉路径,用并查集来判断。

代码:

#include<iostream>
#include<cstring>
using namespace std;
string arrow[100005];
int fa[1000005],in[1000005],out[1000005];
int find(int i){
	if(fa[i]==i)
	return fa[i];
	else{
		fa[i]=find(fa[i]);
		return fa[i];
	}
}
void unions(int x,int y){
	int i=find(x);
	int j=find(y);
	fa[i]=j;
}
int main(){
	int t;
	cin>>t;
	while(t--){
		int n,m;
		scanf("%d%d",&n,&m);
		for(int i=0;i<n*m;i++)//初始化 
		{
			fa[i]=i;
			in[i]=0;
			out[i]=0;
		}
		for(int i=0;i<n;i++){
			cin>>arrow[i];
		}
		for(int i=0;i<n;i++){
			for(int j=0;j<m;j++){
				int a;
				scanf("%d",&a);
				if(arrow[i][j]=='u'&&i-a>=0){
					in[(i-a)*m+j]++;
					out[i*m+j]++;
					unions(i*m+j,(i-a)*m+j);
				}
				else
				if(arrow[i][j]=='d'&&i+a<n){
					in[(i+a)*m+j]++;
					out[i*m+j]++;
					unions(i*m+j,(i+a)*m+j);
				}
				else
				if(arrow[i][j]=='l'&&j-a>=0){
					in[i*m+j-a]++;
					out[i*m+j]++;
					unions(i*m+j,i*m+j-a);
				}
				else
				if(arrow[i][j]=='r'&&j+a<m){
					in[i*m+j+a]++;
					out[i*m+j]++;
					unions(i*m+j,i*m+j+a);
				}
			}
		}
		int fbig=0,fsmall=0,count=0,flag=0;
		for(int i=0;i<n*m;i++){
			if(fa[i]==i)
			flag++;
			if(flag>1)//不联通,有多个连通分量 
			break;
			if(in[i]!=out[i]){
				count++;
				if(in[i]==out[i]+1)
				fbig=1;
				else
				if(in[i]+1==out[i])
				fsmall=1;
			}
		}
		if(count==0&&flag==1)//联通且含有欧拉回路 
		{
			printf("Yes\n");
		}
		else
		if(fbig==1&&fsmall==1&&count==2&&flag==1)//联通且含有欧拉通路 
		{
			printf("Yes\n");
		}
		else
		printf("No\n");
	}
} 

有用的英文单词:grid 网格  pocket 口袋  arrow 箭  tick 打勾

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值