LuoguP9641题解
luan341502 · · 题解
赛时交了八发才过,少考虑了一种情况。
考虑将每个点对应能到的点连起来,这样就构成了一张图(如果对于不满足题目条件的点不进行连边的话,就无法构成一棵基环树)。
观察可以发现只有两种情况满足题目要求:
-
整个图构成一个环,此时从任意点出发都能经过所有点。
-
从一个点出发到达一个环,最终遍历完整个图。
对于两种情况分别判断,用并查集记录即可。
-
所有点在一个并查集内就满足情况。
-
只有一个点入度为零,否则一定不满足情况。统计入度情况进行判断即可。
由于
#include<bits/stdc++.h>
using namespace std;
int n,m;
string str[100005];
int fa[100005],d[100005];
int find(int x){
if(fa[x]==x) return x;
return fa[x]=find(fa[x]);
}
void merge(int x,int y,int x_,int y_){
int s1=(x-1)*m+y,s2=(x_-1)*m+y_;
int u=find(s1),v=find(s2);
if(u!=v) fa[v]=u;
}
void solve(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n*m;i++){
fa[i]=i;
d[i]=0;
}
for(int i=1;i<=n;i++){
cin>>str[i];
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
int x;
scanf("%d",&x);
int ch=(int)str[i][j-1],p,q;
if(ch==117) p=i-x,q=j;
else if(ch==100) p=i+x,q=j;
else if(ch==108) p=i,q=j-x;
else p=i,q=j+x;
if(p<1||q<1||p>n||q>m) continue;
merge(i,j,p,q);
d[(p-1)*m+q]++;
}
}
int x=find(1),cnt=n*m;
for(int i=2;i<=cnt;i++){
if(find(i)!=x){
puts("No");
return;
}
}
int res=0;
for(int i=1;i<=cnt;i++){
if(!d[i]) res++;
if(res>1){
puts("No");
return;
}
}
puts("Yes");
}
int main(){
int t;
cin>>t;
while(t--){
solve();
}
return 0;
}