D. AB Graph
我是SB。
比赛的时候由于有一种情况没有输出 Yes
,挂了,赛后加上就过了。
而且话说这天早上刚考完 WC2021。不觉得WC的这道题和他很像吗。我当时吓出一身冷汗。
好啦不说废话,来分析本题。我们不要把它想得过于复杂,我们分成几种情况。我们令 \(w(u,v)\) 为从 \(u\) 出发,到 \(v\) 的这条边上的字符,令 \(x,y\) 表示这两种字符。
如果存在某两点 \(u,v\),使得 \(w(u,v)\) 和 \(w(v,u)\) 相同,那么我们可以对于任意 \(m\),构造出形如 \(u,v,u,v,u,\cdots\) 的答案,最后的串为 \(x,x,x\cdots\)。显然回文。
如果不存在,说明一定是两点之间的边,有为 a
的,也有为 b
的。如果 \(m\) 为奇数,那么随便找两点我们可以构造如下答案 \(u,v,u,v,\cdots,u,v\),那么经过的边形成的串为 \(x,y,x,\cdots,y,x\),明显回文。
我们只需要处理剩下的 \(m\) 为偶数的情况。我们需要找到如下图的结构:
我们可以在 \(O(n^2)\) 的时间内找到这样的 \(1,2,3\)。易证,在目前讨论的大前提下,对于任意 \(n\geq 3\),都能至少找出一组这样的结构。我们可以构造出以下两种答案,根据 \(m\) 模 \(4\) 的余数决定选择哪一种。
- 第一种,经过的点为 \(3,1,2,1,3,1,2,3,\cdots,3,1,2,1,3,1,2\),得到的串为 \(x,x,y,y,x,x,\cdots,x,x\)。显然回文。
- 第二种,经过的点为 \(1,3,1,2,1,3,1,2,\cdots,1,3,1,2,1\),得到的串为 \(y,x,x,y,y,x,x,y,\cdots,y,x,x,y\)。显然回文。
其他情况输出 NO
。
//Don't act like a loser.
//This code is written by huayucaiji
//You can only use the code for studying or finding mistakes
//Or,you'll be punished by Sakyamuni!!!
//#pragma GCC optimize("Ofast","-funroll-loops","-fdelete-null-pointer-checks")
//#pragma GCC target("ssse3","sse3","sse2","sse","avx2","avx")
#include<bits/stdc++.h>
using namespace std;
int read() {
char ch=getchar();
int f=1,x=0;
while(ch<'0'||ch>'9') {
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') {
x=x*10+ch-'0';
ch=getchar();
}
return f*x;
}
const int MAXN=1e3+10;
int n,m;
char ch[MAXN][MAXN];
signed main() {
int t=read();
while(t--) {
n=read();
m=read();
for(int i=1;i<=n;i++) {
for(int j=1;j<=n;j++) {
cin>>ch[i][j];
}
}
bool flag=0;
for(int i=1;i<=n;i++) {
for(int j=1;j<=n;j++) {
if(i!=j&&ch[i][j]==ch[j][i]) {
printf("YES\n");
for(int k=1;k<=m;k+=2) {
printf("%d %d ",i,j);
}
if((m+1)&1) {
printf("%d\n",i);
}
else {
printf("\n");
}
flag=1;
break;
}
}
if(flag) {
break;
}
}
if(flag) {
continue;
}
if(m&1) {
printf("YES\n");
for(int i=1;i<=m;i+=2) {
printf("1 2 ");
}
cout<<endl;
continue;
}
int a,b,c;
bool fa=0,fb=0,f=0;
for(int i=1;i<=n;i++) {
fa=fb=0;
for(int j=1;j<=n;j++) {
if(ch[i][j]=='a') {
fa=1;
a=j;
}
if(ch[j][i]=='a') {
fb=1;
b=j;
}
}
if(fa&&fb) {
c=i;
f=1;
break;
}
}
if(!f) {
printf("NO\n");
continue;
}
printf("YES\n");
if(m%4==0) {
for(int i=0;i+4<=m;i+=4) {
printf("%d %d %d %d ",c,b,c,a);
}
printf("%d\n",c);
}
else {
for(int i=0;i+4<=m;i+=4) {
printf("%d %d %d %d ",b,c,a,c);
}
printf("%d %d %d\n",b,c,a);
}
}
return 0;
}