题目描述:
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 打勾