Problem:
Big Maze
あなたは Jumbo Amusement Garden，略して「JAG」と呼ばれる巨大な遊園地で働いている．この遊園地の敷地は広大で，アトラクションもことごとく巨大なものが設置される．
この度JAGに，新たな巨大迷路アトラクション「Big Maze」が導入されることになった．
Big Maze の形状は，平面図で見ると，縦横共に
N
マスの正方形状の迷路
M
個を，隣接する左右の辺同士を繋ぎ合わせ，縦
N
マス，横
NM
マスの長方形状になる予定である．
M
個の迷路を左からどの順番で繋ぎ合わせるかはあらかじめ決まっているが，隣り合う迷路のどの辺同士を繋ぎ合わせるかは未定である．
M
個の迷路を繋ぎ合わせる前に，各迷路を90 度回転させる事が出来る．回転は何度でも行うことができ．回数は迷路毎に別々に決めてよい．回転させない迷路があってもかまわない．
各マスは通行可能な「通路」か，通行不可能な「壁」のいずれかであり，Big Maze の内部での移動は，上下左右の 4 方向に隣接する通路のマスに限り可能である．
Big Maze の左端の
N
箇所に位置し，かつ通路であるマスをスタート地点とし，右端の
N
箇所に位置し，かつ通路であるマスをゴール地点とする．
M
個の迷路を繋ぎ合わせる辺の選び方によっては，スタート地点やゴール地点が複数存在する場合や，存在しない場合もあり得る．
また，スタート地点からゴール地点への経路が複数存在する場合や，存在しない場合もあり得る．
あなたの仕事は， 左から繋ぎ合わせる順番があらかじめ決まっている
M
個の迷路を適切に回転させ，繋ぎ合わせる辺を上手く選ぶことで，スタート地点からゴール地点へ通路を移動して到達可能な縦
N
マス，横
NM
マスの長方形状の Big Maze を作ることが出来るか確認することである．
Input
入力は複数のデータセットからなり，各データセットが連続して与えられる．
データセットの数は最大で 50 である．
各データセットは，次の形式で表される．
N
M
maze
1
maze
2
...
maze
M
最初の行はふたつの整数
N
，
M
が空白区切りで与えられ，縦横
N
マスの迷路が
M
個与えられることを示し，
1 ≤ N ≤ 12
かつ
1 ≤ M ≤ 1,
000
である．
続いて，空白無しの
N
文字を 1 行とする
N
行の入力
maze
i
が
M
回続く．
ここで，
1 ≤ i ≤ M
である．
N
行の入力
maze
i
は，左から繋ぎ合わせる順番で数えたときの
i
番目の迷路の情報を表し，以下の形式で与えられる．
c
1, 1
c
1, 2
... c
1, N
c
2, 1
c
2, 2
... c
2, N
...
c
N, 1
c
N, 2
... c
N, N
各
c
j, k
は，“.” または “#” のいずれか 1 文字で，上から
j
番目かつ左から
k
番目のマスの情報を表し，“.” のとき通路，“#”のとき壁である．
ここで，
1 ≤ j, k ≤ N
である．
入力の終わりは，空白で区切られた 2 個のゼロからなる行で示される．
Output
各データセットについて，スタート地点からゴール地点へ移動可能な経路が少なくともひとつ存在する Big Maze を作ることが可能なら “Yes”，不可能なら “No” を 1 行で出力せよ．
Sample Input
3 2
#.#
...
#.#
###
...
###
3 2
#.#
...
#.#
###
#.#
###
3 3
#..
..#
###
..#
#.#
#..
#..
..#
###
5 3
.....
#####
##...
##.##
##...
.....
#####
.....
#####
.....
...##
##.##
...##
#####
.....
3 2
#.#
...
#.#
#.#
#.#
#.#
0 0
Output for Sample Input
Yes
No
Yes
Yes
Yes
以下に，サンプルデータセットの図を示す．

Submitted solutions:

code_snippet: #include<bits/stdc++.h>
using namespace std;

namespace atcoder {
	struct dsu {
	public:
		dsu() : _n(0) {}
		explicit dsu(int n) : _n(n), parent_or_size(n, -1) {}

		int merge(int a, int b) {
			assert(0 <= a && a < _n);
			assert(0 <= b && b < _n);
			int x = leader(a), y = leader(b);
			if (x == y) return x;
			if (-parent_or_size[x] < -parent_or_size[y]) std::swap(x, y);
			parent_or_size[x] += parent_or_size[y];
			parent_or_size[y] = x;
			return x;
		}

		bool same(int a, int b) {
			assert(0 <= a && a < _n);
			assert(0 <= b && b < _n);
			return leader(a) == leader(b);
		}

		int leader(int a) {
			assert(0 <= a && a < _n);
			if (parent_or_size[a] < 0) return a;
			return parent_or_size[a] = leader(parent_or_size[a]);
		}

		int size(int a) {
			assert(0 <= a && a < _n);
			return -parent_or_size[leader(a)];
		}

		std::vector<std::vector<int>> groups() {
			std::vector<int> leader_buf(_n), group_size(_n);
			for (int i = 0; i < _n; i++) {
				leader_buf[i] = leader(i);
				group_size[leader_buf[i]]++;
			}
			std::vector<std::vector<int>> result(_n);
			for (int i = 0; i < _n; i++) {
				result[i].reserve(group_size[i]);
			}
			for (int i = 0; i < _n; i++) {
				result[leader_buf[i]].push_back(i);
			}
			result.erase(
				std::remove_if(result.begin(), result.end(),
							[&](const std::vector<int>& v) { return v.empty(); }),
				result.end());
			return result;
		}

	private:
		int _n;
		// root node: -1 * component size
		// otherwise: parent
		std::vector<int> parent_or_size;
	};
}
using namespace atcoder;
/* BOOST MULTIPRECISION
#include<boost/multiprecision/cpp_int.hpp>
using namespace boost::multiprecision;
//*/

typedef long long ll;

#define rep(i, s, n) for (int i = (int)(s); i < (int)(n); i++)
#define rrep(i, s, n) for (int i = (int)(n)-1; i >= (int)(s); i--)
#define all(v) begin(v),end(v)

template <typename T> bool chmin(T &a, const T &b) {
	if (a <= b) return false;
	a = b;
	return true;
}

template <typename T> bool chmax(T &a, const T &b) {
	if (a >= b) return false;
	a = b;
	return true;
}

template <typename T> T max(vector<T> &a){
	assert(!a.empty());
	T ret = a[0];
	for (int i=0; i<(int)a.size(); i++) chmax(ret, a[i]);
	return ret;
}

template <typename T> T min(vector<T> &a){
	assert(!a.empty());
	T ret = a[0];
	for (int i=0; i<(int)a.size(); i++) chmin(ret, a[i]);
	return ret;
}

template <typename T> T sum(vector<T> &a){
	T ret = 0;
	for (int i=0; i<(int)a.size(); i++) ret += a[i];
	return ret;
}

// importbisect
template <typename T>
int bisect_left(vector<T> &X, T v){
	return lower_bound(X.begin(), X.end(), v) - X.begin();
}

template <typename T>
int bisect_right(vector<T> &X, T v){
	return upper_bound(X.begin(), X.end(), v) - X.begin();
}
// ----

// defcomp
template <typename T>
vector<T> compress(vector<T> &X) {
	vector<T> vals = X;
	sort(vals.begin(), vals.end());
	vals.erase(unique(vals.begin(), vals.end()), vals.end());
	return vals;
}
// -----

// makediv
vector<ll> makediv(ll n){
	vector<ll> ld, ud;
	for (ll i=1; i*i<=n; i++){
		if (n%i == 0){
			ld.push_back(i);
			if (i != n/i){
				ud.push_back(n/i);
			}
		}
	}
	reverse(ud.begin(), ud.end());
	ld.insert(ld.end(), ud.begin(), ud.end());
	return ld;
}
// -----

// Fast Factorization
// https://judge.yosupo.jp/submission/38126
// !!! CHANGED THE PRIMARY TEST !!!
typedef unsigned int uint;

struct Mint {
	uint64_t n;
	static uint64_t mod, inv, r2;
	Mint() : n(0) { }
	Mint(const uint64_t &x) : n(init(x)) { }
	static uint64_t init(const uint64_t &w) { return reduce(__uint128_t(w) * r2); }
	static void set_mod(const uint64_t &m) {
		mod = inv = m;
		for(int i = 0; i < 5; i++)	inv *= 2 - inv * m;
		r2 = -__uint128_t(m) % m;
	}
	static uint64_t reduce(const __uint128_t &x) {
		uint64_t y = uint64_t(x >> 64) - uint64_t((__uint128_t(uint64_t(x) * inv) * mod) >> 64);
		return int64_t(y) < 0 ? y + mod : y;
	}
	Mint& operator+= (const Mint &x) { n += x.n - mod; if(int64_t(n) < 0) n += mod; return *this; }
	Mint& operator+ (const Mint &x) const { return Mint(*this) += x; }
	Mint& operator*= (const Mint &x) { n = reduce(__uint128_t(n) * x.n); return *this; }
	Mint& operator* (const Mint &x) const { return Mint(*this) *= x; }
	uint64_t val() const { return reduce(n); }
};

uint64_t Mint::mod, Mint::inv, Mint::r2;

bool suspect(const uint64_t &a, const uint64_t &s, uint64_t d, const uint64_t &n) {
	if(Mint::mod != n)	Mint::set_mod(n);
	Mint x(1), xx(a), o(x), m(n - 1);
	while(d > 0) {
		if(d & 1)	x *= xx;
		xx *= xx;
		d >>= 1;
	}
	if(x.n == o.n)	return true;
	for(uint r = 0; r < s; r++) {
		if(x.n == m.n)	return true;
		x *= x;
	}
	return false;
}

bool is_prime(const uint64_t &n) {
	if(n <= 1 || (n > 2 && (~n & 1)))	return false;
	uint64_t d = n - 1, s = 0;
	while(~d & 1)	s++, d >>= 1;
	static const uint64_t a_big[] = {2, 325, 9375, 28178, 450775, 9780504, 1795265022};
	static const uint64_t a_smo[] = {2, 7, 61};
	if(n < 4759123141LL) {
		for(auto &&p : a_smo) {
			if(p >= n)	break;
			if(!suspect(p, s, d, n))	return false;
		}
	} else {
		for(auto &&p : a_big) {
			if(p >= n)	break;
			if(!suspect(p, s, d, n))	return false;
		}
	}
	return true;
}

uint64_t rho_pollard(const uint64_t &n) {
	if(~n & 1)	return 2u;
	static random_device rng;
	uniform_int_distribution<uint64_t> rr(1, n - 1);
	if(Mint::mod != n)	Mint::set_mod(n);
	for(;;) {
		uint64_t c_ = rr(rng), g = 1, r = 1, m = 500;
		Mint y(rr(rng)), xx(0), c(c_), ys(0), q(1);
		while(g == 1) {
			xx.n = y.n;
			for(uint i = 1; i <= r; i++)	y *= y, y += c;
			uint64_t k = 0; g = 1;
			while(k < r && g == 1) {
				for(uint i = 1; i <= (m > (r - k) ? (r - k) : m); i++) {
					ys.n = y.n;
					y *= y; y += c;
					uint64_t xxx = xx.val(), yyy = y.val();
					q *= Mint(xxx > yyy ? xxx - yyy : yyy - xxx);
				}
				g = __gcd<uint64_t>(q.val(), n);
				k += m;
			}
			r *= 2;
		}
		if(g == n)	g = 1;
		while(g == 1) {
			ys *= ys; ys += c;
			uint64_t xxx = xx.val(), yyy = ys.val();
			g = __gcd<uint64_t>(xxx > yyy ? xxx - yyy : yyy - xxx, n);
		}
		if(g != n && is_prime(g))	return g;
	}
	assert(69 == 420);
}

template <typename T>
vector<T> inter_factor(const T &n) {
	if(n < 2)	return { };
	if(is_prime(n))	return {n};
	T d = rho_pollard(static_cast<uint64_t>(n));
	vector<T> l = inter_factor(d), r = inter_factor(n / d);
	l.insert(l.end(), r.begin(), r.end());
	return l;
}

template <typename T>
vector<T> factor(T n) {
	vector<T> f1;
	for(uint i = 2; i < 100; i += (i & 1) + 1)
		while(n % i == 0)	f1.push_back(i), n /= i;
	vector<T> f2 = inter_factor(n);
	f1.insert(f1.end(), f2.begin(), f2.end());
	sort(f1.begin(), f1.end());
	return f1;
}

struct grid {
    int h, w;
    grid (int _h = 0, int _w = 0) : h(_h), w(_w) {}
    int idx(int x, int y) const {
        return x * w + y;
    }
    std::pair<int,int> pos(int id) const {
        return {id / w, id % w};
    }
    bool operator()(int x, int y) const {
        return 0 <= x && x < h && 0 <= y && y < w;
    }
    bool operator()(int id) const {
        return operator()(id / w, id % w);
    }
    static constexpr std::array<std::pair<int,int>, 4> dxys = {std::pair<int,int>{0, 1}, {-1, 0}, {0, -1}, {1, 0}};
    auto adj4(int x, int y) const {
        return dxys | std::views::transform([x, y](std::pair<int,int> dxy){
            return std::pair<int,int>(dxy.first + x, dxy.second + y);
        }) | std::views::filter([this](std::pair<int,int> xy){
            return operator()(xy.first, xy.second);
        });
    }
    auto adj4(int id) const {
        return adj4(id / w, id % w) | std::ranges::views::transform([this](std::pair<int,int> xy){
            return idx(xy.first, xy.second);
        });
    }
};

void solve(int n,int m){
	vector maze(m, vector(n,vector<char>(n)));
	rep(i,0,m){
		rep(x,0,n)rep(y,0,n)cin>>maze[i][x][y];
	}

	auto rotate=[&](int i)->void {
		vector<vector<char>> ret(n,vector<char>(n));
		rep(x,0,n){
			rep(y,0,n){
				ret[y][n-1-x]=maze[i][x][y];
			}
		}
		swap(maze[i],ret);
		return;
	};


	auto make_all_state=[&](auto self,vector<char> &var,int i,int mx,vector<vector<int>> &ret,vector<int> &g)-> void {
		if(i==n){
			ret.push_back(g);
			return;
		}
		if(var[i]=='#'){
			g.push_back(-1);
			self(self,var,i+1,mx,ret,g);
			g.pop_back();
		}else{	
			if(i-1>=0 && var[i-1]=='.'){
				g.push_back(g[i-1]);
				self(self,var,i+1,mx,ret,g);
				g.pop_back();
			}else{
				rep(x,0,mx+1){
					g.push_back(x);
					self(self,var,i+1,max(mx,x+1),ret,g);
					g.pop_back();
				}
			}
		}
	};

	vector<pair<vector<int>,int>> last_jotai;

	rep(tar,0,m){
		/*
		cout << tar << endl;
		for(auto g: last_jotai) {
			cout << "g: ";
			for (int x: g.first) cout << x << ' ';
			cout << endl;
			cout << "daihyo: " << g.second << endl;
		}
			*/
		vector<pair<vector<int>,int>> next_jotai;
		rep(num,0,4){
			rotate(tar);
			//cout << num << endl;
			vector<vector<bool>> ikeru(n,vector<bool>(n));
			vector<vector<bool>> ikeru_start(n, vector<bool>(n));
			rep(st,0,n){
				if (maze[tar][st][0]=='#')continue;
				vector seen(n,vector<bool>(n));
				seen[st][0] = 1;
				vector<pair<int,int>> mada;
				mada.push_back(pair(st,0));
				grid g(n,n);
				while(!mada.empty()){
					auto [i,j]=mada.back();
					mada.pop_back();
					for(auto[x,y]:g.adj4(i,j)){
						if(seen[x][y])continue;
						if(maze[tar][x][y]=='#')continue;
						seen[x][y]=1;
						mada.push_back(pair(x,y));
					}
				}
				rep(x,0,n){
					if(seen[x][n-1]){
						ikeru[st][x]=1;
					}
					if(seen[x][0]) {
						ikeru_start[st][x]=1;
					}
				}
			}

			vector<vector<bool>> ikeru_end(n, vector<bool>(n));
			rep(st,0,n){
				if (maze[tar][st][n-1]=='#')continue;
				vector seen(n,vector<bool>(n));
				seen[st][n-1] = 1;
				vector<pair<int,int>> mada;
				mada.push_back(pair(st,n-1));
				grid g(n,n);
				while(!mada.empty()){
					auto [i,j]=mada.back();
					mada.pop_back();
					for(auto[x,y]:g.adj4(i,j)){
						if(seen[x][y])continue;
						if(maze[tar][x][y]=='#')continue;
						seen[x][y]=1;
						mada.push_back(pair(x,y));
					}
				}
				rep(x,0,n){
					if(seen[x][n-1]){
						ikeru_end[st][x]=1;
					}
				}
			}


			
			
			vector<vector<int>> start_states;
			vector<vector<int>> end_states;
			vector<char> start_column(n);
			vector<char> end_column(n);
			int dot_state=0;
			rep(x,0,n){
				start_column[x]=maze[tar][x][0];
				end_column[x]=maze[tar][x][n-1];
				if (start_column[x]=='.')dot_state|=1;
				if (end_column[x]=='.')dot_state|=2;
			}
			if(dot_state!=3)continue;

			/*
			for(char c:start_column)cout<<c;
			cout<<endl;
			*/

			vector<int> g;
			make_all_state(make_all_state,start_column,0,0,start_states,g);
			make_all_state(make_all_state,end_column,0,0,end_states,g);
			map<vector<int>,int> start_taio;
			map<vector<int>,int> end_taio;
			{
				int piv=0;
				for(auto f:start_states){
					start_taio[f]=piv++;
				}
			}
			{
				int piv=0;
				for(auto f:end_states){
					end_taio[f]=piv++;
				}
			}

			vector gogo((int)start_taio.size(), vector<pair<int,int>>(n,pair(-1,-1)));

			rep(f_ind,0,(int)start_states.size()){
				auto& f=start_states[f_ind];
				atcoder::dsu uf(2*n);
				rep(i,0,n) {
					if(start_column[i]=='#')continue;
					rep(j,0,n){
						if(ikeru[i][j]){
							uf.merge(f[i],j+n);
						}
					}
				}
				rep(i,0,n) {
					rep(j,0,n){
						if(ikeru_start[i][j]){
							uf.merge(f[i],f[j]);
						}
					}
				}
				rep(j,0,n){
					rep(k,0,n) {
						if(ikeru_end[j][k]) uf.merge(j+n,k+n);
					}
				}
				map<int,int> st;
				vector<int> f_go(n,-1);
				int piv=0;
				rep(j,0,n){
					if(end_column[j]=='#')continue;
					if(!st.contains(uf.leader(j+n))) {
						st[uf.leader(j+n)]=piv++;
					}
					f_go[j]=st[uf.leader(j+n)];
				}
				rep(j,0,n) {
					if(!st.contains(uf.leader(j)))continue;
					assert(end_taio.contains(f_go));
					gogo[f_ind][j] = pair(end_taio[f_go], st[uf.leader(j)]);
				}
			}



			// tar=0
			if(tar==0) {
				vector<int> init_g(n,-1);
				rep(i,0,n) {
					if (start_column[i]=='#') continue;
					init_g[i]=0;
				}
				int init_start_ind = start_taio[init_g];
				if (gogo[init_start_ind][0].second != -1) {
					next_jotai.push_back(pair(end_states[gogo[init_start_ind][0].first], gogo[init_start_ind][0].second));
				}
			}else{
				rep(h_ind,0,(int)last_jotai.size()) {
					dsu uf(2*n);
					vector<int> init_g(n,-1);
					map<int,int> mp;
					rep(i,0,n) {
						if(start_column[i]=='.'&&last_jotai[h_ind].first[i]!=-1){
							uf.merge(last_jotai[h_ind].first[i],i+n);
						}
					}
					rep(i,0,n) {
						rep(j,0,n){
							if(ikeru_start[i][j]){
								uf.merge(i+n,j+n);
							}
						}
					}
					int piv=0;
					rep(i,0,n) {
						if(start_column[i]=='#'){
							continue;
						}else {
							if(!mp.contains(uf.leader(i+n))) {
								mp[uf.leader(i+n)]=piv++;
							}
							init_g[i]=mp[uf.leader(i+n)];
						}
					}


					assert(start_taio.contains(init_g));
					int init_start_ind = start_taio[init_g];

					if (!mp.contains(uf.leader(last_jotai[h_ind].second)))continue;

					if (gogo[init_start_ind][
						mp[uf.leader(last_jotai[h_ind].second)]
					].second == -1) continue;


					next_jotai.push_back(pair(
						end_states[
							gogo[init_start_ind][mp[uf.leader(last_jotai[h_ind].second)]].first
						],
						gogo[init_start_ind][mp[uf.leader(last_jotai[h_ind].second)]].second)
					);
				}
			}

		}

		sort(next_jotai.begin(),next_jotai.end());
		next_jotai.erase(unique(next_jotai.begin(),next_jotai.end()),next_jotai.end());
		swap(next_jotai,last_jotai);
	}

	if ((int)last_jotai.size() > 0) {
		cout << "Yes\n";
	}else{
		cout << "No\n";
	}


}

void jikken(int n) {
	rep(i,0,1<<n){
		atcoder::dsu uf(n);
		rep(j,0,n-1){
			if((i>>j&1)&&(i>>(j+1)&1))uf.merge(j,j+1);
		}
		vector<ll> dp(n+1);
		dp[0]=1;
		rep(j,0,n){
			if(uf.leader(j)==j&&(i>>j&1)){
				vector<ll> ndp(n+1);
				rep(k,0,n){
					ndp[k+1]+=dp[k];
					ndp[k]+=dp[k]*(k+1);
				}
				swap(dp,ndp);
			}
		}
		if(sum(dp)>=100){
			cout<<sum(dp)<<endl;
		}
	}
}

int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	//jikken(12);
	while(true){
		int n,m;cin>>n>>m;
		if(n==0)break;
		solve(n,m);
	}
}
accuracy: 1
time_ms: 1000
memory_kb: 4352
final_rank: 10

code_snippet: #include<bits/stdc++.h>
using namespace std;

using ll =long long;

using vi=vector<int>;
struct dsu {
  int n;
  vi par;

  dsu(int n) : n(n), par(n, -1){};

  int find(int v) {
    if(par[v] < 0) return v;
    return par[v] = find(par[v]);
  }

  bool merge(int x, int y) {
    x = find(x);
    y = find(y);
    if(x == y) return false;
    if(par[x] > par[y]) swap(x, y);
    par[x] += par[y];
    par[y] = x;
    return true;
  }

  int size(int v) { return -par[find(v)]; }

  bool same(int x, int y) { return find(x) == find(y); }
};

void rotate(vector<string> &S){
	int N=S.size();
	vector<string> T(N);
	for(int i=0;i<N;i++){
		for(int j=0;j<N;j++){
			T[i].push_back(S[j][N-i-1]);
		}
	}
	swap(T,S);
	return;
}

void print(vector<string> &S){
	for(auto s:S)cout<<s<<endl;
	cout<<endl;
}

void print(vector<vector<ll>> &P){
	for(auto V:P){
		for(auto v:V)cout<<v<<",";
		cout<<"/";
	}
	cout<<endl;
}

vector<vector<ll>> MG(int N,vector<vector<ll>> L,vector<vector<ll>> R){
	// print(L);
	// print(R);
	vector<bool> egl(N,0),egr(N,0),EL(N,0),ER(N,0);
	dsu d(N*4);
	for(auto V:L){
		int VN=V.size();
		for(int j=0;j<VN;j++){
			if(j!=0){
				d.merge(V[j],V[j-1]);
			}
			if(V[j]>=N)egl[V[j]-N]=1;
			else EL[V[j]]=1;
		}
	}
	for(auto V:R){
		int VN=V.size();
		for(int j=0;j<VN;j++){
			if(j!=0){
				d.merge(V[j]+2*N,V[j-1]+2*N);
			}
			if(V[j]<N)egr[V[j]]=1;
			else ER[V[j]-N]=1;
		}
	}
	for(int i=0;i<N;i++){
		if(egl[i]&&egr[i]){
			d.merge(i+N,i+2*N);
		}
	}
	vector<vector<ll>> P;
	vector<vector<ll>> memo(4*N);
	for(int i=0;i<4*N;i++){
		if(i<N&&EL[i]){
			memo[d.find(i)].push_back(i);
		}
		if(i>=3*N&&ER[i-3*N]){
			memo[d.find(i)].push_back(i-2*N);
		}
	}
	for(int i=0;i<4*N;i++){
		if(memo[i].size()>0)P.push_back(memo[i]);
	}
	// print(P);
	// cout<<"==============="<<endl;

	return P;
}

void solve(ll N,ll M){
	vector<vector<string>> S(M);
	for(int i=0;i<M;i++){
		S[i].resize(N);
		for(int j=0;j<N;j++){
			cin>>S[i][j];
		}
	}

	vector<vector<vector<vector<ll>>>> P(M,vector<vector<vector<ll>>> (4));
	for(int i=0;i<M;i++){
		for(int t=0;t<4;t++){

			dsu d(N*N);
			for(int h=0;h<N;h++){
				for(int w=0;w<N;w++){
					if(h!=0&&S[i][h][w]=='.'&&S[i][h-1][w]=='.'){
						d.merge(h*N+w,(h-1)*N+w);
					}
					if(w!=0&&S[i][h][w]=='.'&&S[i][h][w-1]=='.'){
						d.merge(h*N+w,h*N+w-1);
					}
				}
			}
			vector<bool> seen(N*N,0);
			for(int h=0;h<N;h++){
				if(seen[h*N])continue;
				if(S[i][h][0]=='#')continue;
				P[i][t].push_back({h});
				for(int j=0;j<N;j++){
					if(j==h)continue;
					if(d.same(h*N,j*N)){
						seen[j*N]=1;
						P[i][t].back().push_back(j);
					}
				}
				for(int j=0;j<N;j++){
					if(d.same(h*N,j*N+N-1)){
						seen[j*N+N-1]=1;
						P[i][t].back().push_back(j+N);
					}
				}
			}

			for(ll h=0;h<N;h++){
				if(seen[h*N+N-1])continue;
				if(S[i][h][N-1]=='#')continue;
				P[i][t].push_back({h+N});
				for(int j=0;j<N;j++){
					if(d.same(h*N+N-1,j*N)){
						seen[j*N]=1;
						P[i][t].back().push_back(j);
					}
				}
				for(int j=0;j<N;j++){
					if(h==j)continue;
					if(d.same(h*N+N-1,j*N+N-1)){
						seen[j*N+N-1]=1;
						P[i][t].back().push_back(j+N);
					}
				}
			}

			// print(S[i]);
			// for(auto V:P[i][t]){
			// 	for(auto v:V)cout<<v<<",";
			// 	cout<<"//";
			// }
			// cout<<endl;
			// cout<<"===================="<<endl;
			rotate(S[i]);
		}
		
	}
	vector<set<vector<vector<ll>>>> DP(M);
	for(int t=0;t<4;t++)DP[0].insert(P[0][t]);
	
	for(int m=1;m<M;m++){
		for(auto s:DP[m-1]){
			for(int t=0;t<4;t++){
				DP[m].insert(MG(N,s,P[m][t]));
			}
		}
	}

	for(auto s:DP[M-1]){
		for(auto V:s){
			bool egL=0,egR=0;
			for(auto v:V){
				if(v<N)egL=1;
				else egR=1;
			}
			if(egL&&egR){
				cout<<"Yes"<<endl;
				return;
			}
		}
	}
	cout<<"No"<<endl;

}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

	ll N,M;
	while(cin>>N>>M,N+M!=0)solve(N,M);
}
accuracy: 1
time_ms: 1560
memory_kb: 13664
final_rank: 12

code_snippet: #include <bits/stdc++.h>
using namespace std;

template<class T>
bool chmin(T &a, const T &b) {if (a > b) {a = b; return 1;} return 0;}

struct UnionFind
{
    int n;
    vector<int> par, siz;
    
    UnionFind() = default;
    UnionFind(int _n) : n(_n), par(_n), siz(_n, 1)
    {
        iota(par.begin(), par.end(), 0);
    }
    
    int root(int x)
    {
        if (par[x] == x) return x;
        else return par[x] = root(par[x]);
    }
    
    bool same(int x, int y)
    {
        return root(x) == root(y);
    }
    
    void merge(int x, int y)
    {
        int rx = root(x), ry = root(y);
        if (rx == ry) return;
        siz[rx] += siz[ry];
        par[ry] = rx;
        return;
    }
    
    int size(int x)
    {
        return siz[root(x)];
    }
    
};

bool is_end = false;

int N, M;

inline bool isvalid(int x, int y)
{
    return 0 <= x && x < N && 0 <= y && y < N;
}

void rotate(vector<vector<bool>> &vec)
{
    vector nvec(N, vector<bool>(N));
    
    for (int i = 0; i < N; ++i)
    {
        for (int j = 0; j < N; ++j)
        {
            nvec[i][j] = vec[j][N-1-i];
        }
    }
    vec = nvec;
    
    return;
}

int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};

void update_uf(vector<vector<bool>> &maze, UnionFind &uf)
{
    int S = N * N;
    UnionFind mp(S + 2 * N);
    for (int x = 0; x < N; ++x)
    {
        for (int y = 0; y < N; ++y)
        {
            if (!maze[x][y]) continue;
            
            int v = x * N + y;
            if (y == 0) mp.merge(v, S + x);
            if (y == N - 1) mp.merge(v, S + N + x);
            
            if (x + 1 < N)
            {
                int nx = x + 1, ny = y, nv = v + N;
                if (maze[x][y] && maze[nx][ny]) mp.merge(v, nv);
            }
            
            if (y + 1 < N)
            {
                int nx = x, ny = y + 1, nv = v + 1;
                if (maze[x][y] && maze[nx][ny]) mp.merge(v, nv);
            }
        }
    }
    
    for (int i = 0; i < 2 * N; ++i)
    {
        for (int j = i + 1; j < 2 * N; ++j)
        {
            int si = S + i, sj = S + j;
            if (mp.same(si, sj)) uf.merge(i, j);
        }
    }
    
    return;
}

void solve()
{
    cin >> N >> M;
    if (N == 0 && M == 0)
    {
        is_end = true;
        return;
    }
    
    vector maze(M, vector(N, vector<bool>(N)));
    for (int i = 0; i < M; ++i)
    {
        for (int j = 0; j < N; ++j)
        {
            string S; cin >> S;
            for (int k = 0; k < N; ++k)
            {
                if (S[k] == '#') maze[i][j][k] = 0;
                else maze[i][j][k] = 1;
            }
        }
    }
    
    const int INF = 1e9;
    vector dp(M+1, vector<vector<int>>());
    
    {
        int i = 0;
        
        for (int r = 0; r < 4; ++r)
        {
            vector<int> par(N, INF);
            for (int x = 0; x < N; ++x)
            {
                if (maze[i][x][0]) par[x] = 0;
            }
            dp[i].emplace_back(par);
            
            rotate(maze[i]);
        }
    }
    
    for (int i = 0; i < M; ++i)
    {
        for (int r = 0; r < 4; ++r)
        {
            UnionFind uf(2*N);
            update_uf(maze[i], uf);
            
            bool debug = (r == 0);
            
            // if (debug)
            // {
            //     cout << -3 << " " << i << " " << r << endl;
            //     for (int x = 0; x < 2*N; ++x)
            //     {
            //         for (int y = 0; y < 2*N; ++y)
            //         {
            //             cout << uf.same(x, y);
            //         }
            //         cout << endl;
            //     }
            // }
            
            for (auto pv : dp[i])
            {
                assert((int)pv.size() == N);
                UnionFind con = uf;
                vector<int> pre(N, -1);
                for (int j = 0; j < N; ++j)
                {
                    int p = pv[j];
                    if (p == INF) continue;
                    else
                    {
                        assert(p < N);
                        if (pre[p] != -1) con.merge(pre[p], j);
                        pre[p] = j;
                    }
                }
                
                // if (debug)
                // {
                //     cout << -3 << " " << i << " " << r << endl;
                //     for (int x = 0; x < 2*N; ++x)
                //     {
                //         for (int y = 0; y < 2*N; ++y)
                //         {
                //             cout << con.same(x, y);
                //         }
                //         cout << endl;
                //     }
                // }
                
                vector<int> val(2*N, INF);
                for (int j = 0; j < N; ++j)
                {
                    int rj = con.root(j);
                    if (con.size(rj) != 1) chmin(val[rj], pv[j]);
                }
                for (int j = N; j < 2*N; ++j)
                {
                    int rj = con.root(j);
                    if (con.size(rj) != 1) chmin(val[rj], j);
                }
                
                
                vector<int> vec(N, INF);
                vector<int> used(2*N, -1);
                used[0] = 0;
                int now = 1;
                bool zero = false;
                for (int j = 0; j < N; ++j)
                {
                    int p = val[con.root(N + j)];
                    if (p == INF) continue;
                    if (p == 0) zero = true;
                    
                    if (used[p] == -1)
                    {
                        used[p] = now;
                        now++;
                    }
                    vec[j] = used[p];
                }
                
                if (zero)
                {
                    dp[i+1].emplace_back(vec);
                    
                    // if (debug)
                    // {
                    //     cout << -2 << " " << i << " " << r << endl;
                    //     for (auto v : vec) cout << v << " ";
                    //     cout << endl;
                    // }
                }
                
            }
            
            rotate(maze[i]);
        }
        
        sort(dp[i+1].begin(), dp[i+1].end());
        dp[i+1].erase(unique(dp[i+1].begin(), dp[i+1].end()), dp[i+1].end());
        
        // if (dp[i+1].size()) cout << i+1 << endl;
        // if (i + 1 == 266)
        // {
        //     for (auto pv : dp[i+1])
        //     {
        //         for (auto v : pv) cout << v << " ";
        //         cout << endl;
        //     }
        // }
        
    }
    
    if (dp[M].size()) cout << "Yes" << endl;
    else cout << "No" << endl;
    
    
    return;
}

int main()
{
    while (!is_end)
    {
        solve();
    }
    
    return 0;
}
accuracy: 1
time_ms: 340
memory_kb: 4524
final_rank: 4

code_snippet: #line 1 "h.cpp"

#line 1 "/Users/nok0/Documents/Programming/nok0/atcoder/dsu.hpp"



#include <algorithm>
#include <cassert>
#include <vector>

namespace atcoder {

// Implement (union by size) + (path compression)
// Reference:
// Zvi Galil and Giuseppe F. Italiano,
// Data structures and algorithms for disjoint set union problems
struct dsu {
  public:
    dsu() : _n(0) {}
    explicit dsu(int n) : _n(n), parent_or_size(n, -1) {}

    int merge(int a, int b) {
        assert(0 <= a && a < _n);
        assert(0 <= b && b < _n);
        int x = leader(a), y = leader(b);
        if (x == y) return x;
        if (-parent_or_size[x] < -parent_or_size[y]) std::swap(x, y);
        parent_or_size[x] += parent_or_size[y];
        parent_or_size[y] = x;
        return x;
    }

    bool same(int a, int b) {
        assert(0 <= a && a < _n);
        assert(0 <= b && b < _n);
        return leader(a) == leader(b);
    }

    int leader(int a) {
        assert(0 <= a && a < _n);
        if (parent_or_size[a] < 0) return a;
        return parent_or_size[a] = leader(parent_or_size[a]);
    }

    int size(int a) {
        assert(0 <= a && a < _n);
        return -parent_or_size[leader(a)];
    }

    std::vector<std::vector<int>> groups() {
        std::vector<int> leader_buf(_n), group_size(_n);
        for (int i = 0; i < _n; i++) {
            leader_buf[i] = leader(i);
            group_size[leader_buf[i]]++;
        }
        std::vector<std::vector<int>> result(_n);
        for (int i = 0; i < _n; i++) {
            result[i].reserve(group_size[i]);
        }
        for (int i = 0; i < _n; i++) {
            result[leader_buf[i]].push_back(i);
        }
        result.erase(
            std::remove_if(result.begin(), result.end(),
                           [&](const std::vector<int>& v) { return v.empty(); }),
            result.end());
        return result;
    }

  private:
    int _n;
    // root node: -1 * component size
    // otherwise: parent
    std::vector<int> parent_or_size;
};

}  // namespace atcoder


#line 1 "/Users/nok0/Documents/Programming/nok0/cftemp.hpp"
#include <bits/stdc++.h>
using namespace std;

#pragma region Macros
// rep macro
#define foa(v, a) for(auto &v : a)
#define REPname(a, b, c, d, e, ...) e
#define REP(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int i = 0; i < (x); ++i)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))
#define REPSname(a, b, c, ...) c
#define REPS(...) REPSname(__VA_ARGS__, REPS1, REPS0)(__VA_ARGS__)
#define REPS0(x) for(int i = 1; i <= (x); ++i)
#define REPS1(i, x) for(int i = 1; i <= (x); ++i)
#define RREPname(a, b, c, d, e, ...) e
#define RREP(...) RREPname(__VA_ARGS__, RREP3, RREP2, RREP1, RREP0)(__VA_ARGS__)
#define RREP0(x) for(int i = (x)-1; i >= 0; --i)
#define RREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define RREP2(i, r, l) for(int i = (r)-1; i >= (l); --i)
#define RREP3(i, r, l, c) for(int i = (r)-1; i >= (l); i -= (c))
#define RREPSname(a, b, c, ...) c
#define RREPS(...) RREPSname(__VA_ARGS__, RREPS1, RREPS0)(__VA_ARGS__)
#define RREPS0(x) for(int i = (x); i >= 1; --i)
#define RREPS1(i, x) for(int i = (x); i >= 1; --i)

// name macro
#define pb push_back
#define eb emplace_back
#define SZ(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define popcnt(x) __builtin_popcountll(x)
template <class T = int>
using V = std::vector<T>;
template <class T = int>
using VV = std::vector<std::vector<T>>;
template <class T>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
using ll = long long;
using ld = long double;
using int128 = __int128_t;
using pii = std::pair<int, int>;
using pll = std::pair<long long, long long>;

// input macro
template <class T, class U>
std::istream &operator>>(std::istream &is, std::pair<T, U> &p) {
	is >> p.first >> p.second;
	return is;
}
template <class T>
std::istream &operator>>(std::istream &is, std::vector<T> &v) {
	for(T &i : v) is >> i;
	return is;
}
std::istream &operator>>(std::istream &is, __int128_t &a) {
	std::string s;
	is >> s;
	__int128_t ret = 0;
	for(int i = 0; i < s.length(); i++)
		if('0' <= s[i] and s[i] <= '9')
			ret = 10 * ret + s[i] - '0';
	a = ret * (s[0] == '-' ? -1 : 1);
	return is;
}
namespace scanner {
void scan(int &a) { std::cin >> a; }
void scan(long long &a) { std::cin >> a; }
void scan(std::string &a) { std::cin >> a; }
void scan(char &a) { std::cin >> a; }
void scan(char a[]) { std::scanf("%s", a); }
void scan(double &a) { std::cin >> a; }
void scan(long double &a) { std::cin >> a; }
template <class T, class U>
void scan(std::pair<T, U> &p) { std::cin >> p; }
template <class T>
void scan(std::vector<T> &a) { std::cin >> a; }
void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &...tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner
#define VEC(type, name, size)     \
	std::vector<type> name(size); \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                                    \
	std::vector<std::vector<type>> name(h, std::vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)             \
	std::string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHAR(...)     \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DOUBLE(...)     \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)

// output-macro
template <class T, class U>
std::ostream &operator<<(std::ostream &os, const std::pair<T, U> &p) {
	os << p.first << " " << p.second;
	return os;
}
template <class T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &a) {
	for(int i = 0; i < int(a.size()); ++i) {
		if(i) os << " ";
		os << a[i];
	}
	return os;
}
std::ostream &operator<<(std::ostream &dest, __int128_t &value) {
	std::ostream::sentry s(dest);
	if(s) {
		__uint128_t tmp = value < 0 ? -value : value;
		char buffer[128];
		char *d = std::end(buffer);
		do {
			--d;
			*d = "0123456789"[tmp % 10];
			tmp /= 10;
		} while(tmp != 0);
		if(value < 0) {
			--d;
			*d = '-';
		}
		int len = std::end(buffer) - d;
		if(dest.rdbuf()->sputn(d, len) != len) {
			dest.setstate(std::ios_base::badbit);
		}
	}
	return dest;
}
template <class T>
void print(const T a) { std::cout << a << '\n'; }
template <class Head, class... Tail>
void print(Head H, Tail... T) {
	std::cout << H << ' ';
	print(T...);
}
template <class T>
void printel(const T a) { std::cout << a << '\n'; }
template <class T>
void printel(const std::vector<T> &a) {
	for(const auto &v : a)
		std::cout << v << '\n';
}
template <class Head, class... Tail>
void printel(Head H, Tail... T) {
	std::cout << H << '\n';
	printel(T...);
}
void Yes(const bool b = true) { std::cout << (b ? "Yes\n" : "No\n"); }
void No() { std::cout << "No\n"; }
void YES(const bool b = true) { std::cout << (b ? "YES\n" : "NO\n"); }
void NO() { std::cout << "NO\n"; }
void err(const bool b = true) {
	if(b) {
		std::cout << "-1\n", exit(0);
	}
}

//debug macro
namespace debugger {
template <class T>
void view(const std::vector<T> &a) {
	std::cerr << "{ ";
	for(const auto &v : a) {
		std::cerr << v << ", ";
	}
	std::cerr << "\b\b }";
}
template <class T>
void view(const std::vector<std::vector<T>> &a) {
	std::cerr << "{\n";
	for(const auto &v : a) {
		std::cerr << "\t";
		view(v);
		std::cerr << "\n";
	}
	std::cerr << "}";
}
template <class T, class U>
void view(const std::vector<std::pair<T, U>> &a) {
	std::cerr << "{\n";
	for(const auto &p : a) std::cerr << "\t(" << p.first << ", " << p.second << ")\n";
	std::cerr << "}";
}
template <class T, class U>
void view(const std::map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &p : m) std::cerr << "\t[" << p.first << "] : " << p.second << "\n";
	std::cerr << "}";
}
template <class T, class U>
void view(const std::pair<T, U> &p) { std::cerr << "(" << p.first << ", " << p.second << ")"; }
template <class T>
void view(const std::set<T> &s) {
	std::cerr << "{ ";
	for(auto &v : s) {
		view(v);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <class T>
void view(const T &e) { std::cerr << e; }
}  // namespace debugger
#ifdef LOCAL
void debug_out() {}
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	debugger::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "\b\b]\n";                                   \
	} while(false)
#else
#define debug(...) (void(0))
#endif

// vector macro
template <class T>
int lb(const std::vector<T> &a, const T x) { return std::distance((a).begin(), std::lower_bound((a).begin(), (a).end(), (x))); }
template <class T>
int ub(const std::vector<T> &a, const T x) { return std::distance((a).begin(), std::upper_bound((a).begin(), (a).end(), (x))); }
template <class T>
void UNIQUE(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<T> press(std::vector<T> &a) {
	auto res = a;
	UNIQUE(res);
	for(auto &v : a)
		v = lb(res, v);
	return res;
}
#define SORTname(a, b, c, ...) c
#define SORT(...) SORTname(__VA_ARGS__, SORT1, SORT0, ...)(__VA_ARGS__)
#define SORT0(a) std::sort((a).begin(), (a).end())
#define SORT1(a, c) std::sort((a).begin(), (a).end(), [](const auto x, const auto y) { return x c y; })
template <class T>
void ADD(std::vector<T> &a, const T x = 1) {
	for(auto &v : a) v += x;
}
template <class T>
void SUB(std::vector<T> &a, const T x = 1) {
	for(auto &v : a) v -= x;
}
std::vector<std::pair<char, int>> rle(const string &s) {
	int n = s.size();
	std::vector<std::pair<char, int>> ret;
	for(int l = 0; l < n;) {
		int r = l + 1;
		for(; r < n and s[l] == s[r]; r++) {}
		ret.emplace_back(s[l], r - l);
		l = r;
	}
	return ret;
}
template <class T>
std::vector<std::pair<T, int>> rle(const std::vector<T> &v) {
	int n = v.size();
	std::vector<std::pair<T, int>> ret;
	for(int l = 0; l < n;) {
		int r = l + 1;
		for(; r < n and v[l] == v[r]; r++) {}
		ret.emplace_back(v[l], r - l);
		l = r;
	}
	return ret;
}
std::vector<int> iota(int n) {
	std::vector<int> p(n);
	std::iota(p.begin(), p.end(), 0);
	return p;
}
template <class T>
struct cum_vector {
public:
	cum_vector() = default;
	template <class U>
	cum_vector(const std::vector<U> &vec) : cum((int)vec.size() + 1) {
		for(int i = 0; i < (int)vec.size(); i++)
			cum[i + 1] = cum[i] + vec[i];
	}
	T prod(int l, int r) {
		return cum[r] - cum[l];
	}

private:
	std::vector<T> cum;
};

// math macro
template <class T, class U>
inline bool chmin(T &a, const U &b) { return a > b ? a = b, true : false; }
template <class T, class U>
inline bool chmax(T &a, const U &b) { return a < b ? a = b, true : false; }
template <class T>
T divup(T x, T y) { return (x + y - 1) / y; }
template <class T>
T POW(T a, long long n) {
	T ret = 1;
	while(n) {
		if(n & 1) ret *= a;
		a *= a;
		n >>= 1;
	}
	return ret;
}
// modpow
long long POW(long long a, long long n, const int mod) {
	long long ret = 1;
	a = (a % mod + mod) % mod;
	while(n) {
		if(n & 1) (ret *= a) %= mod;
		(a *= a) %= mod;
		n >>= 1;
	}
	return ret;
}
template <class T, class F>
T bin_search(T ok, T ng, const F &f) {
	while(abs(ok - ng) > 1) {
		T mid = (ok + ng) >> 1;
		(f(mid) ? ok : ng) = mid;
	}
	return ok;
}
template <class T, class F>
T bin_search(T ok, T ng, const F &f, int loop) {
	for(int i = 0; i < loop; i++) {
		T mid = (ok + ng) / 2;
		(f(mid) ? ok : ng) = mid;
	}
	return ok;
}

// others
struct fast_io {
	fast_io() {
		ios::sync_with_stdio(false);
		cin.tie(nullptr);
		cout << fixed << setprecision(15);
	}
} fast_io_;
const int inf = 1e9;
const ll INF = 1e18;
#pragma endregion

void main_();

int main() {
	main_();
	return 0;
}
#line 4 "h.cpp"

using namespace atcoder;

void main_() {
	while(true) {
		INT(n, m);
		if(n + m == 0) break;
		VV<string> mazes(m);
		REP(i, m) {
			mazes[i].resize(n);
			cin >> mazes[i];
		}
		//vector {-1,1,1,-1,2,2,-1}
		//start 1
		auto to_uf = [&](int i) -> dsu {
			dsu uf(n * n);  // j * n + k

			for(int j = 0; j < n; j++) {
				for(int k = 0; k < n - 1; k++) {
					if(mazes[i][j][k] == '.' && mazes[i][j][k + 1] == '.') {
						uf.merge(j * n + k, j * n + (k + 1));
					}
				}
			}

			for(int j = 0; j < n - 1; j++) {
				for(int k = 0; k < n; k++) {
					if(mazes[i][j][k] == '.' && mazes[i][j + 1][k] == '.') {
						uf.merge(j * n + k, (j + 1) * n + k);
					}
				}
			}

			return uf;
		};

		vector<dsu> uf_data(m);

		REP(i, m) { uf_data[i] = to_uf(i); }

		auto rotate = [&](int x, int y, int dir) -> pair<int, int> {
			if(dir == 0) return make_pair(x, y);
			if(dir == 1) return make_pair(y, n - 1 - x);
			if(dir == 2) return make_pair(n - 1 - x, n - 1 - y);
			if(dir == 3) return make_pair(n - 1 - y, x);
			return {-1, -1};
		};

		//右端の状態 -> 次の右端の状態を求める
		auto nxt = [&](vector<int> bef, int I, int dir) {
			vector<int> nx(n, 0);
			// to_ufは N ^2 マス全部入ってます　連結性が
			auto &mat_uf = uf_data[I];
			vector<int> indices(n * 2, -1);
			REP(i, n) {
				if(!bef[i]) continue;
				auto [x, y] = rotate(i, 0, dir);
				indices[i] = x * n + y;
			}
			REP(i, n, n + n) {
				auto [x, y] = rotate(i - n, n - 1, dir);
				if(mazes[I][x][y] == '#')
					indices[i] = -1;
				else
					indices[i] = x * n + y;
			}

			dsu uf(n * 2);

			REP(i, n * 2)
			REP(j, i + 1, n * 2) {
				if(indices[i] == -1 || indices[j] == -1) continue;
				if(mat_uf.same(indices[i], indices[j])) uf.merge(i, j);
			}

			REP(i, n) {
				if(bef[i] == 0) continue;
				REP(j, i + 1, n) {
					if(bef[i] == bef[j]) uf.merge(i, j);
				}
			}

			int idx = 2;
			for(auto &g : uf.groups()) {
				debug(g);
				int front = g.front();
				if(indices[front] == -1) continue;
				bool is_one = 0;
				foa(v, g) if(v < n and bef[v] == 1) is_one = true;
				if(is_one) {
					foa(v, g) if(v >= n) nx[v - n] = 1;
				} else {
					foa(v, g) if(v >= n) nx[v - n] = idx;
					idx++;
				}
			}

			if(count(all(nx), 1) == 0) {
				return V<>{};
			}
			auto re = press(nx);
			if(re[0] != 0) ADD(nx);
			return nx;
		};

		set<vector<int>> state;
		state.insert(V<>(n, 1));
		REP(k, 0, m) {
			set<vector<int>> nxt_state;
			for(auto &vec : state) {
				REP(dir, 4) {
					auto nx = nxt(vec, k, dir);
					if(!nx.empty())
						nxt_state.insert(nx);
				}
			}
			state = move(nxt_state);
		}
		Yes(SZ(state));
	}
}
accuracy: 1
time_ms: 220
memory_kb: 4432
final_rank: 1

code_snippet: #include <bits/stdc++.h>
#define For(i, a, b) for(int (i)=(int)(a); (i)<(int)(b); ++(i))
#define rFor(i, a, b) for(int (i)=(int)(a)-1; (i)>=(int)(b); --(i))
#define rep(i, n) For(i, 0, n)
#define rrep(i, n) rFor(i, n, 0)
#define fi first
#define se second
using namespace std;
typedef long long lint;
typedef unsigned long long ulint;
typedef pair<int, int> pii;
typedef pair<lint, lint> pll;
template<class T> bool chmax(T &a, const T &b){if(a<b){a=b; return true;} return false;}
template<class T> bool chmin(T &a, const T &b){if(a>b){a=b; return true;} return false;}
template<class T> T div_floor(T a, T b){
    if(b < 0) a *= -1, b *= -1;
    return a>=0 ? a/b : (a+1)/b-1;
}
template<class T> T div_ceil(T a, T b){
    if(b < 0) a *= -1, b *= -1;
    return a>0 ? (a-1)/b+1 : a/b;
}

constexpr lint mod = 1000000007;
constexpr lint INF = mod * mod;
constexpr int MAX = 100010;

typedef struct UnionFindTree{
    vector<int> par;

    UnionFindTree(int n){
        par.resize(n, -1);
    }

    bool is_root(int x){
        return par[x] < 0;
    }

    int find(int x){
        if(is_root(x)) return x;
        return par[x] = find(par[x]);
    }

    int size(int x){
        return -par[find(x)];
    }

    bool unite(int x, int y){
        x = find(x);
        y = find(y);
        if(x == y) return false;
        if(size(x) < size(y)) swap(x, y);
        par[x] += par[y];
        par[y] = x;
        return true;
    }

    bool same(int x, int y){
        return find(x) == find(y);
    }

    void clear(){
        fill(par.begin(), par.end(), -1);
    }
}UF;

using panel = vector<string>;

int n, m;
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};

void rot(panel &a){
    panel b = a;
    rep(i, n)rep(j, n) b[j][n-1-i] = a[i][j];
    rep(i, n)rep(j, n) a[i][j] = b[i][j];
}

void normalize(vector<int> &state){
    map<int, int> id;
    rep(i, state.size()){
        if(id.find(state[i]) == id.end()){
            id[state[i]] = i;
            state[i] = i;
        }
        else state[i] = id[state[i]];
    }
    return;
}

void solve(){
    vector<panel> ps(m);
    rep(i, m){
        ps[i].resize(n);
        rep(j, n) cin >> ps[i][j];
    }
    set<vector<int>> prev_states, new_states;
    rep(new_panel, m){
        rep(_, 4){
            UF uf(n * n);
            rep(x, n)rep(y, n)if(ps[new_panel][x][y] == '.'){
                rep(i, 4){
                    int nx = x + dx[i], ny = y + dy[i];
                    if(0 <= nx && nx < n && 0 <= ny && ny < n && ps[new_panel][nx][ny] == '.'){
                        uf.unite(x * n + y, nx * n + ny);
                    }
                }
            }
            vector<int> panel_state(n * 2);
            rep(i, n){
                panel_state[i] = uf.find(i * n);
                panel_state[i + n] = uf.find(i * n + n - 1);
            }
            normalize(panel_state);

            if(new_panel == 0){
                bool connected = false;
                rep(i, n)if(panel_state[i + n] < n){
                    if(ps[new_panel][panel_state[i + n]][0] == '.') connected = true;
                    break;
                }
                if(connected) new_states.insert(panel_state);
                rot(ps[new_panel]);
                continue;
            }

            UF uf2(n * 4);
            for(auto &prev_state: prev_states){
                uf2.clear();
                rep(i, n * 2) uf2.unite(i, prev_state[i]);
                rep(i, n) uf2.unite(i + n, i + 2 * n);
                rep(i, n * 2) uf2.unite(i + 2 * n, panel_state[i] + 2 * n);
                vector<int> new_state(n * 2);
                rep(i, n){
                    new_state[i] = uf2.find(i);
                    new_state[i + n] = uf2.find(i + 3 * n);
                }
                normalize(new_state);
                bool connected = false;
                rep(i, n)if(new_state[i + n] < n){
                    if(ps[new_panel][panel_state[i + n]][0] == '.') connected = true;
                    break;
                }
                if(connected) new_states.insert(new_state);
            }

            rot(ps[new_panel]);
        }
        swap(prev_states, new_states);
        new_states.clear();
    }
    puts(!prev_states.empty() ? "Yes" : "No");
}

int main(){
    while(scanf("%d%d", &n, &m) && n){
        solve();
    }
}
accuracy: 1
time_ms: 690
memory_kb: 4024
final_rank: 8

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define SIZE 15

struct Info{
	Info(int arg_row,int arg_col){
		row = arg_row;
		col = arg_col;
	}
	int row,col;
};

int N,num_maze;
int boss[3*SIZE],height[3*SIZE];
ll POW[3*SIZE],CODE[3*SIZE];
int diff_row[4] = {-1,0,0,1},diff_col[4] = {0,-1,1,0};
char input[SIZE][SIZE],used[3*SIZE];
bool visited[SIZE][SIZE];
vector<ll> data[4][1005];
map<vector<ll>,bool> MAP;

bool rangeCheck(int row,int col){

	return row >= 0 && row <= N-1 && col >= 0 && col <= N-1;
}

int get_boss(int id){
	if(boss[id] == id)return id;
	else{
		return boss[id] = get_boss(boss[id]);
	}
}

int isSame(int x,int y){
	return get_boss(x) == get_boss(y);
}

void unite(int x,int y){
	int boss_x = get_boss(x);
	int boss_y = get_boss(y);

	//既に同じグループなら何もしない
	if(boss_x == boss_y)return;

	//高さが高い方に吸収する
	if(height[x] > height[y]){

		boss[boss_y] = boss_x;

	}else if(height[x] < height[y]){

		boss[boss_x] = boss_y;

	}else{ //height[x] == height[y]

		boss[boss_y] = boss_x;
		height[x]++;
	}
}

void init(){

	for(int i = 0; i < 2*N; i++){

		boss[i] = i;
		height[i] = 0;
	}
}


void roll_90(char table[SIZE][SIZE]){

	char tmp[SIZE][SIZE];

	for(int row = 0; row < N; row++){
		for(int col = 0; col < N; col++){
			tmp[col][N-1-row] = table[row][col];
		}
	}

	for(int row = 0; row < N; row++){
		for(int col = 0; col < N; col++){
			table[row][col] = tmp[row][col];
		}
	}
}

void func(){

	for(int i = 0; i < 4; i++){
		for(int k = 0; k < 1005; k++){

			data[i][k].clear();
		}
	}

	queue<Info> Q;

	for(int i = 0; i < num_maze; i++){

		for(int row = 0; row < N; row++){
			scanf("%s",input[row]);
		}

		for(int loop = 0; loop < 4; loop++){ //表を回転させ、右端と左端の連結性を調べておく

			roll_90(input);

			vector<ll> tmp_data;

			for(int start_row = 0; start_row < N; start_row++){

				if(input[start_row][0] == '#')continue;

				init();

				for(int row = 0; row < N; row++){
					for(int col = 0; col < N; col++){
						visited[row][col] = false;
					}
				}

				for(int k = 0; k < 2*N; k++){

					CODE[k] = 0;
				}

				visited[start_row][0] = true;
				Q.push(Info(start_row,0));

				while(!Q.empty()){

					for(int a = 0; a < 4; a++){

						int adj_row = Q.front().row+diff_row[a];
						int adj_col = Q.front().col+diff_col[a];

						if(rangeCheck(adj_row,adj_col) == false || input[adj_row][adj_col] == '#' ||
								visited[adj_row][adj_col] == true)continue;

						visited[adj_row][adj_col] = true;
						Q.push(Info(adj_row,adj_col));
					}

					Q.pop();
				}

				//★他のstart_rowとのグループ化★
				for(int other_start_row = 0; other_start_row < N; other_start_row++){
					if(other_start_row == start_row)continue;

					if(visited[other_start_row][0]){
						unite(start_row,other_start_row);
					}
				}

				for(int goal_row = 0; goal_row < N; goal_row++){

					if(visited[goal_row][N-1]){

						unite(start_row,N+goal_row);
					}
				}

				for(int k = 0; k < 2*N; k++){
					if((k < N && visited[k][0] == false) || (k >= N && visited[k-N][N-1] == false))continue;

					CODE[get_boss(k)] += POW[k];
				}

				for(int k = 0; k < 2*N; k++){

					if(CODE[k] == 0)continue;
					tmp_data.push_back(CODE[k]);
				}
			}

			for(int goal_row = 0; goal_row < N; goal_row++){ //★★折り返し対策★★

				if(input[goal_row][N-1] == '#')continue;

				init();

				for(int row = 0; row < N; row++){
					for(int col = 0; col < N; col++){
						visited[row][col] = false;
					}
				}

				for(int k = 0; k < 2*N; k++){

					CODE[k] = 0;
				}

				visited[goal_row][N-1] = true;
				Q.push(Info(goal_row,N-1));

				while(!Q.empty()){

					for(int a = 0; a < 4; a++){

						int adj_row = Q.front().row+diff_row[a];
						int adj_col = Q.front().col+diff_col[a];

						if(rangeCheck(adj_row,adj_col) == false || input[adj_row][adj_col] == '#' ||
								visited[adj_row][adj_col] == true)continue;

						visited[adj_row][adj_col] = true;
						Q.push(Info(adj_row,adj_col));
					}

					Q.pop();
				}

				bool left_FLG = false;

				for(int row = 0; row < N; row++){
					if(visited[row][0]){

						left_FLG = true;
						break;
					}
				}

				if(left_FLG)continue; //計上済なのでSKIP

				//★他のgoal_rowとのグループ化
				for(int other_goal_row = 0; other_goal_row < N; other_goal_row++){
					if(other_goal_row == goal_row)continue;

					if(visited[other_goal_row][N-1]){

						unite(N+goal_row,N+other_goal_row);
					}
				}

				for(int k = N; k < 2*N; k++){
					if(!visited[k-N][N-1])continue;

					CODE[get_boss(k)] += POW[k];
				}

				for(int k = N; k < 2*N; k++){

					if(CODE[k] == 0)continue;
					tmp_data.push_back(CODE[k]);
				}
			}
			sort(tmp_data.begin(),tmp_data.end());
			tmp_data.erase(unique(tmp_data.begin(),tmp_data.end()),tmp_data.end());

			//少なくとも1つ、左端&右端にビットが立っているグループを持っているか調べる
			bool FLG = false;

			for(int a = 0; a < tmp_data.size(); a++){ //グループのループ

				for(int b = 0; b < N; b++){

					if(tmp_data[a] & POW[b]){
						for(int c = N; c < 2*N; c++){
							if(tmp_data[a] & POW[c]){
								FLG = true;
								break;
							}
						}
						if(FLG)break;
					}
				}
				if(FLG)break;
			}

			if(!FLG)continue;

			data[loop][i] = tmp_data;
		}
	}

	vector<vector<ll>> PRE,NEXT;

	for(int loop = 0; loop < 4; loop++){ //スタートのマップ

		if(data[loop][0].size() == 0)continue;

		PRE.emplace_back(data[loop][0]);
	}

	for(int right = 1; right < num_maze; right++){ //マップのループ(右側となる)

		MAP.clear();

		for(int left = 0; left < PRE.size(); left++){ //左側のループ
			for(int roll = 0; roll < 4; roll++){ //右側に連結する、マップrightの回転のループ

				vector<ll> work;

				for(int a = 0; a < data[roll][right].size(); a++){

					work.push_back(data[roll][right][a]*POW[N]); //★【左のマップの右端コード==右のマップの左端コード】にする★
				}

				vector<ll> tmp_data;

				for(int a = 0; a < 3*N; a++){
					boss[a] = a;
					height[a] = 0;
					used[a] = false;
					CODE[a] = 0;
				}

				int parent;

				//左側の連結成分情報を反映
				for(int a = 0; a < PRE[left].size(); a++){
					//代表をどれか1つ選ぶ
					for(int b = 0; b < 2*N; b++){
						if(PRE[left][a] & POW[b]){
							used[b] = true;
							parent = b;
							break;
						}
					}
					for(int b = 0; b < 2*N; b++){
						if(b == parent)continue;
						if(PRE[left][a] & POW[b]){
							used[b] = true;
							unite(parent,b);
						}
					}
				}

				//右側の連結成分情報を反映
				for(int a = 0; a < work.size(); a++){
					//代表をどれか1つ選ぶ
					for(int b = N; b < 3*N; b++){ //★インデックスに注意★
						if(work[a] & POW[b]){
							used[b] = true;
							parent = b;
							break;
						}
					}
					for(int b = N; b < 3*N; b++){
						if(b == parent)continue;
						if(work[a] & POW[b]){
							used[b] = true;
							unite(parent,b);
						}
					}
				}

				//左端
				for(int a = 0; a < N; a++){
					if(!used[a])continue;

					CODE[get_boss(a)] += POW[a];
				}

				//★中間は抜く★

				//右端
				for(int a = 2*N; a < 3*N; a++){
					if(!used[a])continue;

					CODE[get_boss(a)] += POW[a-N]; //加算分を減じる
				}

				for(int a = 0; a < 3*N; a++){

					if(CODE[a] == 0)continue;
					tmp_data.push_back(CODE[a]);
				}

				sort(tmp_data.begin(),tmp_data.end());

				auto at = MAP.find(tmp_data);
				if(at != MAP.end())continue;

				//少なくとも1つ、左端&右端にビットが立っているグループを持っているか調べる
				bool FLG = false;

				for(int a = 0; a < tmp_data.size(); a++){
					for(int p = N; p < 2*N; p++){
						if(tmp_data[a] & POW[p]){
							for(int q = 0; q < N; q++){
								if(tmp_data[a] & POW[q]){

									FLG = true;
									break;
								}
							}
							if(FLG)break;
						}
					}
					if(FLG)break;
				}

				if(!FLG)continue; //ゴールできない、または右のマップに渡れないので不可

				MAP[tmp_data] = true;

				NEXT.emplace_back(tmp_data);
			}
		}
		PRE.clear();
		PRE = NEXT;
		NEXT.clear();
	}

	//左端と右端が連結しているコードがあるか調べる
	for(int i = 0; i < PRE.size(); i++){
		for(int k = 0; k < PRE[i].size(); k++){
			for(int p = N; p < 2*N; p++){
				if(PRE[i][k] & POW[p]){ //少なくとも右端にビットが立っている
					for(int q = 0; q < N; q++){
						if(PRE[i][k] & POW[q]){

							printf("Yes\n");
							return;
						}
					}
				}
			}
		}
	}

	printf("No\n");
}

int main(){

	POW[0] = 1;
	for(int i = 1; i < 3*SIZE; i++){

		POW[i] = POW[i-1]*2;
	}

	while(true){
		scanf("%d %d",&N,&num_maze);
		if(N == 0 && num_maze == 0)break;

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 520
memory_kb: 3500
final_rank: 5

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define SIZE 15

struct Info{
	Info(int arg_row,int arg_col){
		row = arg_row;
		col = arg_col;
	}
	int row,col;
};

struct Data{
	Data(ll arg_code,bool arg_used){
		code = arg_code;
		used = arg_used;
	}
	bool operator<(const struct Data &arg) const{
		return code < arg.code;
	}
	bool operator==(const struct Data &arg) const{

		return code == arg.code;
	}

	ll code;
	bool used;
};

struct Group{
	Group(){
		code = 0;
		start_FLG = false;
	}

	Group(ll arg_code,bool arg_start_FLG){
		code = arg_code;
		start_FLG = arg_start_FLG;
	}
	bool operator<(const struct Group &arg) const{
		return code < arg.code;
	}
	bool operator==(const struct Group &arg) const{

		return code == arg.code;
	}
	ll code;
	bool start_FLG;
};

int N,num_maze;
int boss[3*SIZE],height[3*SIZE];
ll POW[3*SIZE],CODE[3*SIZE];
int diff_row[4] = {-1,0,0,1},diff_col[4] = {0,-1,1,0};
char input[SIZE][SIZE],used[3*SIZE];
bool visited[SIZE][SIZE],start_array[3*SIZE];
vector<Data> STATES[4][1005];


bool rangeCheck(int row,int col){

	return row >= 0 && row <= N-1 && col >= 0 && col <= N-1;
}

int get_boss(int id){
	if(boss[id] == id)return id;
	else{
		return boss[id] = get_boss(boss[id]);
	}
}

int isSame(int x,int y){
	return get_boss(x) == get_boss(y);
}

void unite(int x,int y){
	int boss_x = get_boss(x);
	int boss_y = get_boss(y);

	//既に同じグループなら何もしない
	if(boss_x == boss_y)return;

	//高さが高い方に吸収する
	if(height[x] > height[y]){

		boss[boss_y] = boss_x;

	}else if(height[x] < height[y]){

		boss[boss_x] = boss_y;

	}else{ //height[x] == height[y]

		boss[boss_y] = boss_x;
		height[x]++;
	}
}

void unite_2(int x,int y){
	int boss_x = get_boss(x);
	int boss_y = get_boss(y);

	//既に同じグループなら何もしない
	if(boss_x == boss_y)return;

	//高さが高い方に吸収する
	if(height[x] > height[y]){

		start_array[boss_x] |= start_array[boss_y];
		boss[boss_y] = boss_x;

	}else if(height[x] < height[y]){

		start_array[boss_y] |= start_array[boss_x];
		boss[boss_x] = boss_y;

	}else{ //height[x] == height[y]

		start_array[boss_x] |= start_array[boss_y];
		boss[boss_y] = boss_x;
		height[x]++;
	}
}

void init(){

	for(int i = 0; i < 2*N; i++){

		boss[i] = i;
		height[i] = 0;
	}

	for(int row = 0; row < N; row++){
		for(int col = 0; col < N; col++){

			visited[row][col] = false;
		}
	}

	for(int i = 0; i < 2*N; i++){

		CODE[i] = 0;
	}
}


void roll_90(char table[SIZE][SIZE]){

	char tmp[SIZE][SIZE];

	for(int row = 0; row < N; row++){
		for(int col = 0; col < N; col++){
			tmp[col][N-1-row] = table[row][col];
		}
	}

	for(int row = 0; row < N; row++){
		for(int col = 0; col < N; col++){
			table[row][col] = tmp[row][col];
		}
	}
}

void func(){

	for(int i = 0; i < 4; i++){
		for(int k = 0; k < num_maze; k++){

			STATES[i][k].clear();
		}
	}

	queue<Info> Q;

	for(int i = 0; i < num_maze; i++){

		for(int row = 0; row < N; row++){
			scanf("%s",input[row]);
		}

		for(int loop = 0; loop < 4; loop++){ //表を回転させ、右端と左端の「到達可能性関係」を調べておく

			roll_90(input);
			init();

			for(int start_row = 0; start_row < N; start_row++){

				if(input[start_row][0] == '#' || visited[start_row][0] == true)continue;

				visited[start_row][0] = true;
				Q.push(Info(start_row,0));

				while(!Q.empty()){

					for(int a = 0; a < 4; a++){

						int adj_row = Q.front().row+diff_row[a];
						int adj_col = Q.front().col+diff_col[a];

						if(rangeCheck(adj_row,adj_col) == false || input[adj_row][adj_col] == '#' ||
								visited[adj_row][adj_col] == true)continue;

						visited[adj_row][adj_col] = true;
						Q.push(Info(adj_row,adj_col));
					}

					Q.pop();
				}

				//★他のstart_rowとのグループ化★
				for(int other_start_row = 0; other_start_row < N; other_start_row++){
					if(other_start_row == start_row)continue;

					if(visited[other_start_row][0]){
						//printf("%d-%dをunite\n",start_row,other_start_row);
						unite(start_row,other_start_row);
					}
				}

				for(int goal_row = 0; goal_row < N; goal_row++){

					if(visited[goal_row][N-1]){
						unite(start_row,N+goal_row);
					}
				}

				for(int k = 0; k < 2*N; k++){
					if(get_boss(k) != get_boss(start_row))continue; //start_rowと同グループのみ計上

					CODE[get_boss(k)] += POW[k];
				}

				for(int k = 0; k < 2*N; k++){

					if(CODE[k] == 0 || k != get_boss(start_row))continue;
					STATES[loop][i].push_back(Data(CODE[k],false));
				}
			}

			for(int goal_row = 0; goal_row < N; goal_row++){ //★★折り返し対策★★

				if(input[goal_row][N-1] == '#' || visited[goal_row][N-1] == true)continue;

				visited[goal_row][N-1] = true;
				Q.push(Info(goal_row,N-1));

				while(!Q.empty()){

					for(int a = 0; a < 4; a++){

						int adj_row = Q.front().row+diff_row[a];
						int adj_col = Q.front().col+diff_col[a];

						if(rangeCheck(adj_row,adj_col) == false || input[adj_row][adj_col] == '#' ||
								visited[adj_row][adj_col] == true)continue;

						visited[adj_row][adj_col] = true;
						Q.push(Info(adj_row,adj_col));
					}

					Q.pop();
				}

				//★他のgoal_rowとのグループ化(左端と接続することはないはず)★
				for(int other_goal_row = 0; other_goal_row < N; other_goal_row++){
					if(other_goal_row == goal_row)continue;

					if(visited[other_goal_row][N-1]){

						unite(N+goal_row,N+other_goal_row);
					}
				}

				for(int k = N; k < 2*N; k++){
					if(get_boss(k) != get_boss(goal_row))continue; //goal_rowと同グループのみ計上

					CODE[get_boss(k)] += POW[k];
				}

				for(int k = N; k < 2*N; k++){

					if(CODE[k] == 0 || k != get_boss(goal_row))continue;
					STATES[loop][i].push_back(Data(CODE[k],false));
				}
			}
			sort(STATES[loop][i].begin(),STATES[loop][i].end());
			STATES[loop][i].erase(unique(STATES[loop][i].begin(),STATES[loop][i].end()),STATES[loop][i].end());
		}
	}

	vector<Group> PRE[4],CURRENT[4];

	for(int loop = 0; loop < 4; loop++){

		for(int k = 0; k < STATES[loop][0].size(); k++){ //左端マップの,コードの走査【コードと、start_FLGを紐づける】
			bool start_FLG = false;
			for(int a = 0; a < N; a++){
				if(STATES[loop][0][k].code & (1 << a)){
					start_FLG = true;
					break;
				}
			}
			PRE[loop].push_back(Group(STATES[loop][0][k].code,start_FLG));
		}
	}

	vector<ll> work[4];

	for(int i = 1; i < num_maze; i++){

		for(int loop = 0; loop < 4; loop++){

			work[loop].clear();
		}

		for(int loop = 0; loop < 4; loop++){
			//STATES[loop][i]の各要素にNを加え、一時的なコードを作る
			for(int k = 0; k < STATES[loop][i].size(); k++){
				work[loop].push_back(STATES[loop][i][k].code*POW[N]);
			}
		}

		//コードをマージする
		for(int a_loop = 0; a_loop < 4; a_loop++){//左マップの回転のループ
			for(int b_loop = 0; b_loop < 4; b_loop++){ //右マップの回転のループ

				//UnionFind木を使う
				for(int k = 0; k < 3*N; k++){

					boss[k] = k;
					height[k] = 0;
					start_array[k] = false;
					CODE[k] = 0;
					used[k] = false;
				}

				int parent;

				//左マップの情報の反映
				for(int a = 0; a < PRE[a_loop].size(); a++){

					if(PRE[a_loop][a].start_FLG){ //startを出発している状態ならば、UF木に情報を反映

						for(int k = 0; k < 2*N; k++){
							if(PRE[a_loop][a].code & (1 << k)){
								start_array[k] = true;
							}
						}
					}

					for(int p = 0; p < 2*N; p++){
						if(PRE[a_loop][a].code & (1 << p)){
							used[p] = true;
							parent = p;
							break;
						}
					}
					for(int p = 0; p < 2*N; p++){
						if(p == parent)continue;
						if(PRE[a_loop][a].code & (1 << p)){
							used[p] = true;
							unite_2(parent,p);
						}
					}
				}

				//右マップの情報の反映
				for(int b = 0; b < work[b_loop].size(); b++){
					for(int p = N; p < 3*N; p++){
						if(work[b_loop][b] & (1 << p)){
							used[p] = true;
							parent = p;
							break;
						}
					}
					for(int p = N; p < 3*N; p++){
						if(p == parent)continue;
						if(work[b_loop][b] & (1 << p)){
							used[p] = true;
							unite_2(parent,p);
						}
					}
				}

				bool FLG = false; //少なくとも1組、左端(スタートと連結しているもの)と右端が繋がっているか調べる
				for(int p = 0; p < N; p++){
					if(!used[p])continue;
					if(start_array[get_boss(p)] == true){

												FLG = true;
												break;
											}
				/*	for(int q = 2*N; q < 3*N; q++){
						if(!used[q])continue;
						if(get_boss(p) == get_boss(q) && start_array[get_boss(p)] == true){

							FLG = true;
							break;
						}
					}
					if(FLG)break;*/
				}

				if(!FLG)continue;

				////中間を除きつつ,新しくGroupを作る
				for(int k = 0; k < N; k++){
					if(!used[k])continue;
					CODE[get_boss(k)] += POW[k];
				}
				for(int k = 2*N; k < 3*N; k++){
					if(!used[k])continue;
					CODE[get_boss(k)] += POW[k-N]; //★★元々足してあったNを引く★★
				}

				for(int k = 0; k < 3*N; k++){
					if(CODE[k] == 0)continue;
					CURRENT[a_loop].push_back(Group(CODE[k],start_array[k]));
				}
			}

			sort(CURRENT[a_loop].begin(),CURRENT[a_loop].end());
			CURRENT[a_loop].erase(unique(CURRENT[a_loop].begin(),CURRENT[a_loop].end()),CURRENT[a_loop].end());
		}

		for(int loop = 0; loop < 4; loop++){

			PRE[loop].clear();
			PRE[loop] = CURRENT[loop];
			CURRENT[loop].clear();
		}
	}

	for(int a = 0; a < 4; a++){
		for(int i = 0; i < PRE[a].size(); i++){
			if(!PRE[a][i].start_FLG)continue;
			for(int loop = N; loop < 2*N; loop++){
				if(PRE[a][i].code & (1 << loop)){
					printf("Yes\n");
					return;
				}
			}
		}
	}

	printf("No\n");
}

int main(){

	POW[0] = 1;
	for(int i = 1; i < 3*SIZE; i++){

		POW[i] = POW[i-1]*2;
	}

	while(true){
		scanf("%d %d",&N,&num_maze);
		if(N == 0 && num_maze == 0)break;

		func();
	}

	return 0;
}
accuracy: 0.5
time_ms: 210
memory_kb: 3772
final_rank: 15

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define SIZE 15

struct Info{
	Info(int arg_row,int arg_col){
		row = arg_row;
		col = arg_col;
	}
	int row,col;
};

struct Data{
	Data(ll arg_code,bool arg_used){
		code = arg_code;
		used = arg_used;
	}
	bool operator<(const struct Data &arg) const{
		return code < arg.code;
	}
	bool operator==(const struct Data &arg) const{

		return code == arg.code;
	}

	ll code;
	bool used;
};

struct Group{
	Group(){
		code = 0;
		start_FLG = false;
	}

	Group(ll arg_code,bool arg_start_FLG){
		code = arg_code;
		start_FLG = arg_start_FLG;
	}
	bool operator<(const struct Group &arg) const{
		return code < arg.code;
	}
	bool operator==(const struct Group &arg) const{

		return code == arg.code;
	}
	ll code;
	bool start_FLG;
};

int N,num_maze;
int boss[3*SIZE],height[3*SIZE];
ll POW[3*SIZE],CODE[3*SIZE];
int diff_row[4] = {-1,0,0,1},diff_col[4] = {0,-1,1,0};
char input[SIZE][SIZE],used[3*SIZE];
bool visited[SIZE][SIZE],start_array[3*SIZE];
vector<Data> STATES[4][1005];


bool rangeCheck(int row,int col){

	return row >= 0 && row <= N-1 && col >= 0 && col <= N-1;
}

int get_boss(int id){
	if(boss[id] == id)return id;
	else{
		return boss[id] = get_boss(boss[id]);
	}
}

int isSame(int x,int y){
	return get_boss(x) == get_boss(y);
}

void unite(int x,int y){
	int boss_x = get_boss(x);
	int boss_y = get_boss(y);

	//既に同じグループなら何もしない
	if(boss_x == boss_y)return;

	//高さが高い方に吸収する
	if(height[x] > height[y]){

		boss[boss_y] = boss_x;

	}else if(height[x] < height[y]){

		boss[boss_x] = boss_y;

	}else{ //height[x] == height[y]

		boss[boss_y] = boss_x;
		height[x]++;
	}
}

void unite_2(int x,int y){
	int boss_x = get_boss(x);
	int boss_y = get_boss(y);

	//既に同じグループなら何もしない
	if(boss_x == boss_y)return;

	//高さが高い方に吸収する
	if(height[x] > height[y]){

		start_array[boss_x] |= start_array[boss_y];
		boss[boss_y] = boss_x;

	}else if(height[x] < height[y]){

		start_array[boss_y] |= start_array[boss_x];
		boss[boss_x] = boss_y;

	}else{ //height[x] == height[y]

		start_array[boss_x] |= start_array[boss_y];
		boss[boss_y] = boss_x;
		height[x]++;
	}
}

void init(){

	for(int i = 0; i < 2*N; i++){

		boss[i] = i;
		height[i] = 0;
	}

	for(int row = 0; row < N; row++){
		for(int col = 0; col < N; col++){

			visited[row][col] = false;
		}
	}

	for(int i = 0; i < 2*N; i++){

		CODE[i] = 0;
	}
}


void roll_90(char table[SIZE][SIZE]){

	char tmp[SIZE][SIZE];

	for(int row = 0; row < N; row++){
		for(int col = 0; col < N; col++){
			tmp[col][N-1-row] = table[row][col];
		}
	}

	for(int row = 0; row < N; row++){
		for(int col = 0; col < N; col++){
			table[row][col] = tmp[row][col];
		}
	}
}

void func(){

	for(int i = 0; i < 4; i++){
		for(int k = 0; k < num_maze; k++){

			STATES[i][k].clear();
		}
	}

	queue<Info> Q;

	for(int i = 0; i < num_maze; i++){

		for(int row = 0; row < N; row++){
			scanf("%s",input[row]);
		}

		for(int loop = 0; loop < 4; loop++){ //表を回転させ、右端と左端の「到達可能性関係」を調べておく

			roll_90(input);
			init();

			for(int start_row = 0; start_row < N; start_row++){

				if(input[start_row][0] == '#' || visited[start_row][0] == true)continue;

				visited[start_row][0] = true;
				Q.push(Info(start_row,0));

				while(!Q.empty()){

					for(int a = 0; a < 4; a++){

						int adj_row = Q.front().row+diff_row[a];
						int adj_col = Q.front().col+diff_col[a];

						if(rangeCheck(adj_row,adj_col) == false || input[adj_row][adj_col] == '#' ||
								visited[adj_row][adj_col] == true)continue;

						visited[adj_row][adj_col] = true;
						Q.push(Info(adj_row,adj_col));
					}

					Q.pop();
				}

				//★他のstart_rowとのグループ化★
				for(int other_start_row = 0; other_start_row < N; other_start_row++){
					if(other_start_row == start_row)continue;

					if(visited[other_start_row][0]){
						//printf("%d-%dをunite\n",start_row,other_start_row);
						unite(start_row,other_start_row);
					}
				}

				for(int goal_row = 0; goal_row < N; goal_row++){

					if(visited[goal_row][N-1]){
						unite(start_row,N+goal_row);
					}
				}

				for(int k = 0; k < 2*N; k++){
					if(get_boss(k) != get_boss(start_row))continue; //start_rowと同グループのみ計上

					CODE[get_boss(k)] += POW[k];
				}

				for(int k = 0; k < 2*N; k++){

					if(CODE[k] == 0 || k != get_boss(start_row))continue;
					STATES[loop][i].push_back(Data(CODE[k],false));
				}
			}

			for(int goal_row = 0; goal_row < N; goal_row++){ //★★折り返し対策★★

				if(input[goal_row][N-1] == '#' || visited[goal_row][N-1] == true)continue;

				visited[goal_row][N-1] = true;
				Q.push(Info(goal_row,N-1));

				while(!Q.empty()){

					for(int a = 0; a < 4; a++){

						int adj_row = Q.front().row+diff_row[a];
						int adj_col = Q.front().col+diff_col[a];

						if(rangeCheck(adj_row,adj_col) == false || input[adj_row][adj_col] == '#' ||
								visited[adj_row][adj_col] == true)continue;

						visited[adj_row][adj_col] = true;
						Q.push(Info(adj_row,adj_col));
					}

					Q.pop();
				}

				//★他のgoal_rowとのグループ化(左端と接続することはないはず)★
				for(int other_goal_row = 0; other_goal_row < N; other_goal_row++){
					if(other_goal_row == goal_row)continue;

					if(visited[other_goal_row][N-1]){

						unite(N+goal_row,N+other_goal_row);
					}
				}

				for(int k = N; k < 2*N; k++){
					if(get_boss(k) != get_boss(goal_row))continue; //goal_rowと同グループのみ計上

					CODE[get_boss(k)] += POW[k];
				}

				for(int k = N; k < 2*N; k++){

					if(CODE[k] == 0 || k != get_boss(goal_row))continue;
					STATES[loop][i].push_back(Data(CODE[k],false));
				}
			}
			sort(STATES[loop][i].begin(),STATES[loop][i].end());
			STATES[loop][i].erase(unique(STATES[loop][i].begin(),STATES[loop][i].end()),STATES[loop][i].end());
		}
	}

	vector<Group> PRE[4],CURRENT[4];

	for(int loop = 0; loop < 4; loop++){

		for(int k = 0; k < STATES[loop][0].size(); k++){ //左端マップの,コードの走査【コードと、start_FLGを紐づける】
			bool start_FLG = false;
			for(int a = 0; a < N; a++){
				if(STATES[loop][0][k].code & (1 << a)){
					start_FLG = true;
					break;
				}
			}
			PRE[loop].push_back(Group(STATES[loop][0][k].code,start_FLG));
		}
	}

	vector<ll> work[4];

	for(int i = 1; i < num_maze; i++){

		for(int loop = 0; loop < 4; loop++){

			work[loop].clear();
		}

		for(int loop = 0; loop < 4; loop++){
			//STATES[loop][i]の各要素にNを加え、一時的なコードを作る
			for(int k = 0; k < STATES[loop][i].size(); k++){
				work[loop].push_back(STATES[loop][i][k].code*POW[N]);
			}
		}

		//コードをマージする
		for(int a_loop = 0; a_loop < 4; a_loop++){//左マップの回転のループ
			for(int b_loop = 0; b_loop < 4; b_loop++){ //右マップの回転のループ

				//UnionFind木を使う
				for(int k = 0; k < 3*N; k++){

					boss[k] = k;
					height[k] = 0;
					start_array[k] = false;
					CODE[k] = 0;
					used[k] = false;
				}

				int parent;

				//左マップの情報の反映
				for(int a = 0; a < PRE[a_loop].size(); a++){

					if(PRE[a_loop][a].start_FLG){ //startを出発している状態ならば、UF木に情報を反映

						for(int k = 0; k < 2*N; k++){
							if(PRE[a_loop][a].code & (1 << k)){
								start_array[k] = true;
							}
						}
					}

					for(int p = 0; p < 2*N; p++){
						if(PRE[a_loop][a].code & (1 << p)){
							used[p] = true;
							parent = p;
						}
					}
					for(int p = 0; p < 2*N; p++){
						if(p == parent)continue;
						if(PRE[a_loop][a].code & (1 << p)){
							used[p] = true;
							unite_2(parent,p);
						}
					}
				}

				//右マップの情報の反映
				for(int b = 0; b < work[b_loop].size(); b++){
					for(int p = N; p < 3*N; p++){
						if(work[b_loop][b] & (1 << p)){
							used[p] = true;
							parent = p;
						}
					}
					for(int p = N; p < 3*N; p++){
						if(p == parent)continue;
						if(work[b_loop][b] & (1 << p)){
							used[p] = true;
							unite_2(parent,p);
						}
					}
				}

				bool FLG = false; //少なくとも1組、左端(スタートと連結)と右端が繋がっているか調べる
				for(int p = 0; p < N; p++){
					if(!used[p])continue;
					for(int q = 2*N; q < 3*N; q++){
						if(!used[q])continue;
						if(get_boss(p) == get_boss(q) && start_array[get_boss(p)] == true){

							FLG = true;
							break;
						}
					}
					if(FLG)break;
				}

				if(!FLG)continue;

				////中間を除きつつ,新しくGroupを作る
				for(int k = 0; k < N; k++){
					if(!used[k])continue;
					CODE[get_boss(k)] += POW[k];
				}
				for(int k = 2*N; k < 3*N; k++){
					if(!used[k])continue;
					CODE[get_boss(k)] += POW[k-N]; //★★元々足してあったNを引く★★
				}

				for(int k = 0; k < 3*N; k++){
					if(CODE[k] == 0)continue;
					CURRENT[a_loop].push_back(Group(CODE[k],start_array[k]));
				}
			}

			sort(CURRENT[a_loop].begin(),CURRENT[a_loop].end());
			CURRENT[a_loop].erase(unique(CURRENT[a_loop].begin(),CURRENT[a_loop].end()),CURRENT[a_loop].end());
		}

		for(int loop = 0; loop < 4; loop++){

			PRE[loop].clear();
			PRE[loop] = CURRENT[loop];
			CURRENT[loop].clear();
		}
	}

	for(int a = 0; a < 4; a++){
		for(int i = 0; i < PRE[a].size(); i++){
			if(!PRE[a][i].start_FLG)continue;
			for(int loop = N; loop < 2*N; loop++){
				if(PRE[a][i].code & (1 << loop)){
					printf("Yes\n");
					return;
				}
			}
		}
	}

	printf("No\n");
}

int main(){

	POW[0] = 1;
	for(int i = 1; i < 3*SIZE; i++){

		POW[i] = POW[i-1]*2;
	}

	while(true){
		scanf("%d %d",&N,&num_maze);
		if(N == 0 && num_maze == 0)break;

		func();
	}

	return 0;
}
accuracy: 0.5
time_ms: 220
memory_kb: 3596
final_rank: 14

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define SIZE 15

struct Info{
	Info(int arg_row,int arg_col){
		row = arg_row;
		col = arg_col;
	}
	int row,col;
};

struct Data{
	Data(ll arg_code,bool arg_used){
		code = arg_code;
		used = arg_used;
	}
	bool operator<(const struct Data &arg) const{
		return code < arg.code;
	}
	bool operator==(const struct Data &arg) const{

		return code == arg.code;
	}

	ll code;
	bool used;
};

struct Group{
	Group(){
		code = 0;
		start_FLG = false;
	}

	Group(ll arg_code,bool arg_start_FLG){
		code = arg_code;
		start_FLG = arg_start_FLG;
	}
	bool operator<(const struct Group &arg) const{
		return code < arg.code;
	}
	bool operator==(const struct Group &arg) const{

		return code == arg.code;
	}
	ll code;
	bool start_FLG;
};

int N,num_maze;
int boss[3*SIZE],height[3*SIZE];
ll POW[3*SIZE],CODE[3*SIZE];
int diff_row[4] = {-1,0,0,1},diff_col[4] = {0,-1,1,0};
char input[SIZE][SIZE],used[3*SIZE];
bool visited[SIZE][SIZE],start_array[3*SIZE];
vector<Data> STATES[4][1005];


bool rangeCheck(int row,int col){

	return row >= 0 && row <= N-1 && col >= 0 && col <= N-1;
}

int get_boss(int id){
	if(boss[id] == id)return id;
	else{
		return boss[id] = get_boss(boss[id]);
	}
}

int isSame(int x,int y){
	return get_boss(x) == get_boss(y);
}

void unite(int x,int y){
	int boss_x = get_boss(x);
	int boss_y = get_boss(y);

	//既に同じグループなら何もしない
	if(boss_x == boss_y)return;

	//高さが高い方に吸収する
	if(height[x] > height[y]){

		boss[boss_y] = boss_x;

	}else if(height[x] < height[y]){

		boss[boss_x] = boss_y;

	}else{ //height[x] == height[y]

		boss[boss_y] = boss_x;
		height[x]++;
	}
}

void unite_2(int x,int y){
	int boss_x = get_boss(x);
	int boss_y = get_boss(y);

	//既に同じグループなら何もしない
	if(boss_x == boss_y)return;

	//高さが高い方に吸収する
	if(height[x] > height[y]){

		start_array[boss_x] |= start_array[boss_y];
		boss[boss_y] = boss_x;

	}else if(height[x] < height[y]){

		start_array[boss_y] |= start_array[boss_x];
		boss[boss_x] = boss_y;

	}else{ //height[x] == height[y]

		start_array[boss_x] |= start_array[boss_y];
		boss[boss_y] = boss_x;
		height[x]++;
	}
}

void init(){

	for(int i = 0; i < 2*N; i++){

		boss[i] = i;
		height[i] = 0;
	}

	for(int row = 0; row < N; row++){
		for(int col = 0; col < N; col++){

			visited[row][col] = false;
		}
	}

	for(int i = 0; i < 2*N; i++){

		CODE[i] = 0;
	}
}


void roll_90(char table[SIZE][SIZE]){

	char tmp[SIZE][SIZE];

	for(int row = 0; row < N; row++){
		for(int col = 0; col < N; col++){
			tmp[col][N-1-row] = table[row][col];
		}
	}

	for(int row = 0; row < N; row++){
		for(int col = 0; col < N; col++){
			table[row][col] = tmp[row][col];
		}
	}
}

void func(){

	for(int i = 0; i < 4; i++){
		for(int k = 0; k < num_maze; k++){

			STATES[i][k].clear();
		}
	}

	queue<Info> Q;

	for(int i = 0; i < num_maze; i++){

		for(int row = 0; row < N; row++){
			scanf("%s",input[row]);
		}

		for(int loop = 0; loop < 4; loop++){ //表を回転させ、右端と左端の「到達可能性関係」を調べておく

			roll_90(input);
			init();

			for(int start_row = 0; start_row < N; start_row++){

				if(input[start_row][0] == '#' || visited[start_row][0] == true)continue;

				visited[start_row][0] = true;
				Q.push(Info(start_row,0));

				while(!Q.empty()){

					for(int a = 0; a < 4; a++){

						int adj_row = Q.front().row+diff_row[a];
						int adj_col = Q.front().col+diff_col[a];

						if(rangeCheck(adj_row,adj_col) == false || input[adj_row][adj_col] == '#' ||
								visited[adj_row][adj_col] == true)continue;

						visited[adj_row][adj_col] = true;
						Q.push(Info(adj_row,adj_col));
					}

					Q.pop();
				}

				//★他のstart_rowとのグループ化★
				for(int other_start_row = 0; other_start_row < N; other_start_row++){
					if(other_start_row == start_row)continue;

					if(visited[other_start_row][0]){
						//printf("%d-%dをunite\n",start_row,other_start_row);
						unite(start_row,other_start_row);
					}
				}

				for(int goal_row = 0; goal_row < N; goal_row++){

					if(visited[goal_row][N-1]){
						unite(start_row,N+goal_row);
					}
				}

				for(int k = 0; k < 2*N; k++){
					if(get_boss(k) != get_boss(start_row))continue; //start_rowと同グループのみ計上

					CODE[get_boss(k)] += POW[k];
				}

				for(int k = 0; k < 2*N; k++){

					if(CODE[k] == 0 || k != get_boss(start_row))continue;
					STATES[loop][i].push_back(Data(CODE[k],false));
				}
			}

			for(int goal_row = 0; goal_row < N; goal_row++){ //★★折り返し対策★★

				if(input[goal_row][N-1] == '#' || visited[goal_row][N-1] == true)continue;

				visited[goal_row][N-1] = true;
				Q.push(Info(goal_row,N-1));

				while(!Q.empty()){

					for(int a = 0; a < 4; a++){

						int adj_row = Q.front().row+diff_row[a];
						int adj_col = Q.front().col+diff_col[a];

						if(rangeCheck(adj_row,adj_col) == false || input[adj_row][adj_col] == '#' ||
								visited[adj_row][adj_col] == true)continue;

						visited[adj_row][adj_col] = true;
						Q.push(Info(adj_row,adj_col));
					}

					Q.pop();
				}

				//★他のgoal_rowとのグループ化(左端と接続することはないはず)★
				for(int other_goal_row = 0; other_goal_row < N; other_goal_row++){
					if(other_goal_row == goal_row)continue;

					if(visited[other_goal_row][N-1]){

						unite(N+goal_row,N+other_goal_row);
					}
				}

				for(int k = N; k < 2*N; k++){
					if(get_boss(k) != get_boss(goal_row))continue; //goal_rowと同グループのみ計上

					CODE[get_boss(k)] += POW[k];
				}

				for(int k = N; k < 2*N; k++){

					if(CODE[k] == 0 || k != get_boss(goal_row))continue;
					STATES[loop][i].push_back(Data(CODE[k],false));
				}
			}
			sort(STATES[loop][i].begin(),STATES[loop][i].end());
			STATES[loop][i].erase(unique(STATES[loop][i].begin(),STATES[loop][i].end()),STATES[loop][i].end());
		}
	}

	vector<Group> PRE[4],CURRENT[4];

	for(int loop = 0; loop < 4; loop++){

		for(int k = 0; k < STATES[loop][0].size(); k++){ //左端マップの,コードの走査【コードと、start_FLGを紐づける】
			bool start_FLG = false;
			for(int a = 0; a < N; a++){
				if(STATES[loop][0][k].code & (1 << a)){
					start_FLG = true;
					break;
				}
			}
			PRE[loop].push_back(Group(STATES[loop][0][k].code,start_FLG));
		}
	}

	vector<ll> work[4];

	for(int i = 1; i < num_maze; i++){

		for(int loop = 0; loop < 4; loop++){

			work[loop].clear();
		}

		for(int loop = 0; loop < 4; loop++){
			//STATES[loop][i]の各要素にNを加え、一時的なコードを作る
			for(int k = 0; k < STATES[loop][i].size(); k++){
				work[loop].push_back(STATES[loop][i][k].code*POW[N]);
			}
		}

		//コードをマージする
		for(int a_loop = 0; a_loop < 4; a_loop++){//左マップの回転のループ
			for(int b_loop = 0; b_loop < 4; b_loop++){ //右マップの回転のループ

				//UnionFind木を使う
				for(int k = 0; k < 3*N; k++){

					boss[k] = k;
					height[k] = 0;
					start_array[k] = false;
					CODE[k] = 0;
					used[k] = false;
				}

				int parent;

				//左マップの情報の反映
				for(int a = 0; a < PRE[a_loop].size(); a++){

					if(PRE[a_loop][a].start_FLG){ //startを出発している状態ならば、UF木に情報を反映

						for(int k = 0; k < 2*N; k++){
							if(PRE[a_loop][a].code & (1 << k)){
								start_array[k] = true;
							}
						}
					}

					for(int p = 0; p < 2*N; p++){
						if(PRE[a_loop][a].code & (1 << p)){
							used[p] = true;
							parent = p;
						}
					}
					for(int p = 0; p < 2*N; p++){
						if(p == parent)continue;
						if(PRE[a_loop][a].code & (1 << p)){
							used[p] = true;
							unite_2(parent,p);
						}
					}
				}

				//右マップの情報の反映
				for(int b = 0; b < work[b_loop].size(); b++){
					for(int p = N; p < 3*N; p++){
						if(work[b_loop][b] & (1 << p)){
							used[p] = true;
							parent = p;
						}
					}
					for(int p = N; p < 3*N; p++){
						if(p == parent)continue;
						if(work[b_loop][b] & (1 << p)){
							used[p] = true;
							unite_2(parent,p);
						}
					}
				}

				bool FLG = false; //少なくとも1組、左端(スタートと連結)と右端が繋がっているか調べる
				for(int p = 0; p < N; p++){
					if(!used[p])continue;
					for(int q = 2*N; q < 3*N; q++){
						if(!used[q])continue;
						if(get_boss(p) == get_boss(q) && start_array[p] == true){

							FLG = true;
							break;
						}
					}
					if(FLG)break;
				}

				if(!FLG)continue;

				////中間を除きつつ,新しくGroupを作る
				for(int k = 0; k < N; k++){
					if(!used[k])continue;
					CODE[get_boss(k)] += POW[k];
				}
				for(int k = 2*N; k < 3*N; k++){
					if(!used[k])continue;
					CODE[get_boss(k)] += POW[k-N]; //★★元々足してあったNを引く★★
				}

				for(int k = 0; k < 3*N; k++){
					if(CODE[k] == 0)continue;
					CURRENT[a_loop].push_back(Group(CODE[k],start_array[k]));
				}
			}

			sort(CURRENT[a_loop].begin(),CURRENT[a_loop].end());
			CURRENT[a_loop].erase(unique(CURRENT[a_loop].begin(),CURRENT[a_loop].end()),CURRENT[a_loop].end());
		}

		for(int loop = 0; loop < 4; loop++){

			PRE[loop].clear();
			PRE[loop] = CURRENT[loop];
			CURRENT[loop].clear();
		}
	}

	for(int a = 0; a < 4; a++){
		for(int i = 0; i < PRE[a].size(); i++){
			if(!PRE[a][i].start_FLG)continue;
			for(int loop = N; loop < 2*N; loop++){
				if(PRE[a][i].code & (1 << loop)){
					printf("Yes\n");
					return;
				}
			}
		}
	}

	printf("No\n");
}

int main(){

	POW[0] = 1;
	for(int i = 1; i < 3*SIZE; i++){

		POW[i] = POW[i-1]*2;
	}

	while(true){
		scanf("%d %d",&N,&num_maze);
		if(N == 0 && num_maze == 0)break;

		func();
	}

	return 0;
}
accuracy: 0.5
time_ms: 210
memory_kb: 3672
final_rank: 13

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define SIZE 15

struct Info{
	Info(int arg_row,int arg_col){
		row = arg_row;
		col = arg_col;
	}
	int row,col;
};

struct Data{
	Data(ll arg_code,bool arg_used){
		code = arg_code;
		used = arg_used;
	}
	bool operator<(const struct Data &arg) const{
		return code < arg.code;
	}
	bool operator==(const struct Data &arg) const{

		return code == arg.code;
	}

	ll code;
	bool used;
};

struct Group{
	Group(){
		code = 0;
		start_FLG = false;
	}

	Group(ll arg_code,bool arg_start_FLG){
		code = arg_code;
		start_FLG = arg_start_FLG;
	}
	bool operator<(const struct Group &arg) const{
		return code < arg.code;
	}
	bool operator==(const struct Group &arg) const{

		return code == arg.code;
	}
	ll code;
	bool start_FLG;
};

int N,num_maze;
int boss[3*SIZE],height[3*SIZE];
ll POW[3*SIZE],CODE[3*SIZE];
int diff_row[4] = {-1,0,0,1},diff_col[4] = {0,-1,1,0};
char input[SIZE][SIZE],used[3*SIZE];
bool visited[SIZE][SIZE],start_array[3*SIZE];
vector<Data> STATES[4][1005];


bool rangeCheck(int row,int col){

	return row >= 0 && row <= N-1 && col >= 0 && col <= N-1;
}

int get_boss(int id){
	if(boss[id] == id)return id;
	else{
		return boss[id] = get_boss(boss[id]);
	}
}

int isSame(int x,int y){
	return get_boss(x) == get_boss(y);
}

void unite(int x,int y){
	int boss_x = get_boss(x);
	int boss_y = get_boss(y);

	//既に同じグループなら何もしない
	if(boss_x == boss_y)return;

	//高さが高い方に吸収する
	if(height[x] > height[y]){

		boss[boss_y] = boss_x;

	}else if(height[x] < height[y]){

		boss[boss_x] = boss_y;

	}else{ //height[x] == height[y]

		boss[boss_y] = boss_x;
		height[x]++;
	}
}

void unite_2(int x,int y){
	int boss_x = get_boss(x);
	int boss_y = get_boss(y);

	//既に同じグループなら何もしない
	if(boss_x == boss_y)return;

	//高さが高い方に吸収する
	if(height[x] > height[y]){

		start_array[boss_x] |= start_array[boss_y];
		boss[boss_y] = boss_x;

	}else if(height[x] < height[y]){

		start_array[boss_y] |= start_array[boss_x];
		boss[boss_x] = boss_y;

	}else{ //height[x] == height[y]

		start_array[boss_x] |= start_array[boss_y];
		boss[boss_y] = boss_x;
		height[x]++;
	}
}

void init(){

	for(int i = 0; i < 2*N; i++){

		boss[i] = i;
		height[i] = 0;
	}

	for(int row = 0; row < N; row++){
		for(int col = 0; col < N; col++){

			visited[row][col] = false;
		}
	}

	for(int i = 0; i < 2*N; i++){

		CODE[i] = 0;
	}
}


void roll_90(char table[SIZE][SIZE]){

	char tmp[SIZE][SIZE];

	for(int row = 0; row < N; row++){
		for(int col = 0; col < N; col++){
			tmp[col][N-1-row] = table[row][col];
		}
	}

	for(int row = 0; row < N; row++){
		for(int col = 0; col < N; col++){
			table[row][col] = tmp[row][col];
		}
	}
}

void func(){

	for(int i = 0; i < 4; i++){
		for(int k = 0; k < num_maze; k++){

			STATES[i][k].clear();
		}
	}

	queue<Info> Q;

	for(int i = 0; i < num_maze; i++){

		for(int row = 0; row < N; row++){
			scanf("%s",input[row]);
		}

		for(int loop = 0; loop < 4; loop++){ //表を回転させ、右端と左端の「到達可能性関係」を調べておく

			roll_90(input);
			init();

			for(int start_row = 0; start_row < N; start_row++){

				if(input[start_row][0] == '#' || visited[start_row][0] == true)continue;

				visited[start_row][0] = true;
				Q.push(Info(start_row,0));

				while(!Q.empty()){

					for(int a = 0; a < 4; a++){

						int adj_row = Q.front().row+diff_row[a];
						int adj_col = Q.front().col+diff_col[a];

						if(rangeCheck(adj_row,adj_col) == false || input[adj_row][adj_col] == '#' ||
								visited[adj_row][adj_col] == true)continue;

						visited[adj_row][adj_col] = true;
						Q.push(Info(adj_row,adj_col));
					}

					Q.pop();
				}

				//★他のstart_rowとのグループ化★
				for(int other_start_row = 0; other_start_row < N; other_start_row++){
					if(other_start_row == start_row)continue;

					if(visited[other_start_row][0]){
						//printf("%d-%dをunite\n",start_row,other_start_row);
						unite(start_row,other_start_row);
					}
				}

				for(int goal_row = 0; goal_row < N; goal_row++){

					if(visited[goal_row][N-1]){
						unite(start_row,N+goal_row);
					}
				}

				for(int k = 0; k < 2*N; k++){
					if(get_boss(k) != get_boss(start_row))continue; //start_rowと同グループのみ計上

					CODE[get_boss(k)] += POW[k];
				}

				for(int k = 0; k < 2*N; k++){

					if(CODE[k] == 0)continue;
					STATES[loop][i].push_back(Data(CODE[k],false));
				}
			}

			for(int goal_row = 0; goal_row < N; goal_row++){ //★★折り返し対策★★

				if(input[goal_row][N-1] == '#' || visited[goal_row][N-1] == true)continue;

				visited[goal_row][N-1] = true;
				Q.push(Info(goal_row,N-1));

				while(!Q.empty()){

					for(int a = 0; a < 4; a++){

						int adj_row = Q.front().row+diff_row[a];
						int adj_col = Q.front().col+diff_col[a];

						if(rangeCheck(adj_row,adj_col) == false || input[adj_row][adj_col] == '#' ||
								visited[adj_row][adj_col] == true)continue;

						visited[adj_row][adj_col] = true;
						Q.push(Info(adj_row,adj_col));
					}

					Q.pop();
				}

				//★他のgoal_rowとのグループ化(左端と接続することはないはず)★
				for(int other_goal_row = 0; other_goal_row < N; other_goal_row++){
					if(other_goal_row == goal_row)continue;

					if(visited[other_goal_row][N-1]){

						unite(N+goal_row,N+other_goal_row);
					}
				}

				for(int k = N; k < 2*N; k++){
					if(get_boss(k) != get_boss(goal_row))continue; //goal_rowと同グループのみ計上

					CODE[get_boss(k)] += POW[k];
				}

				for(int k = N; k < 2*N; k++){

					if(CODE[k] == 0)continue;
					STATES[loop][i].push_back(Data(CODE[k],false));
				}
			}
			sort(STATES[loop][i].begin(),STATES[loop][i].end());
			STATES[loop][i].erase(unique(STATES[loop][i].begin(),STATES[loop][i].end()),STATES[loop][i].end());
		}
	}

	vector<Group> PRE[4],CURRENT[4];

	for(int loop = 0; loop < 4; loop++){

		for(int k = 0; k < STATES[loop][0].size(); k++){ //左端マップの,コードの走査【コードと、start_FLGを紐づける】
			bool start_FLG = false;
			for(int a = 0; a < N; a++){
				if(STATES[loop][0][k].code & (1 << a)){
					start_FLG = true;
					break;
				}
			}
			PRE[loop].push_back(Group(STATES[loop][0][k].code,start_FLG));
		}
	}

	vector<ll> work[4];

	for(int i = 1; i < num_maze; i++){

		for(int loop = 0; loop < 4; loop++){

			work[loop].clear();
		}

		for(int loop = 0; loop < 4; loop++){
			//STATES[loop][i]の各要素にNを加え、一時的なコードを作る
			for(int k = 0; k < STATES[loop][i].size(); k++){

				/*ll tmp_code = 0;

				for(int loop_2 = 0; loop_2 < 2*N; loop_2++){
					if(STATES[loop][i][k].code & (1 << loop_2)){

						tmp_code += POW[loop_2+N];
					}
				}*/
				work[loop].push_back(STATES[loop][i][k].code*POW[N]);
			}
		}

		//コードをマージする
		for(int a_loop = 0; a_loop < 4; a_loop++){//左マップの回転のループ
			for(int b_loop = 0; b_loop < 4; b_loop++){ //右マップの回転のループ

				//UnionFind木を使う
				for(int k = 0; k < 3*N; k++){

					boss[k] = k;
					height[k] = 0;
					start_array[k] = false;
					CODE[k] = 0;
					used[k] = false;
				}

				int parent;

				//左マップの情報の反映
				for(int a = 0; a < PRE[a_loop].size(); a++){

					if(PRE[a_loop][a].start_FLG){ //startを出発している状態ならば、UF木に情報を反映

						for(int k = 0; k < 2*N; k++){
							if(PRE[a_loop][a].code & (1 << k)){
								start_array[k] = true;
							}
						}
					}

					for(int p = 0; p < 2*N; p++){
						if(PRE[a_loop][a].code & (1 << p)){
							used[p] = true;
							parent = p;
						}
					}
					for(int p = 0; p < 2*N; p++){
						if(p == parent)continue;
						if(PRE[a_loop][a].code & (1 << p)){
							used[p] = true;
							unite_2(parent,p);
						}
					}
				}

				//右マップの情報の反映
				for(int b = 0; b < work[b_loop].size(); b++){
					for(int p = N; p < 3*N; p++){
						if(work[b_loop][b] & (1 << p)){
							used[p] = true;
							parent = p;
						}
					}
					for(int p = N; p < 3*N; p++){
						if(p == parent)continue;
						if(work[b_loop][b] & (1 << p)){
							used[p] = true;
							unite_2(parent,p);
						}
					}
				}

				bool FLG = false; //少なくとも1組、左端(スタートと連結)と右端が繋がっているか調べる
				for(int p = 0; p < N; p++){
					if(!used[p])continue;
					for(int q = 2*N; q < 3*N; q++){
						if(!used[q])continue;
						if(get_boss(p) == get_boss(q) && start_array[p] == true){

							FLG = true;
							break;
						}
					}
					if(FLG)break;
				}

				if(!FLG)continue;

				////中間を除きつつ,新しくGroupを作る
				for(int k = 0; k < N; k++){
					if(!used[k])continue;
					CODE[get_boss(k)] += POW[k];
				}
				for(int k = 2*N; k < 3*N; k++){
					if(!used[k])continue;
					CODE[get_boss(k)] += POW[k-N]; //★★元々足してあったNを引く★★
				}

				for(int k = 0; k < 3*N; k++){
					if(CODE[k] == 0)continue;
					CURRENT[a_loop].push_back(Group(CODE[k],start_array[k]));
				}
			}

			sort(CURRENT[a_loop].begin(),CURRENT[a_loop].end());
			CURRENT[a_loop].erase(unique(CURRENT[a_loop].begin(),CURRENT[a_loop].end()),CURRENT[a_loop].end());
		}

		for(int loop = 0; loop < 4; loop++){

			PRE[loop].clear();
			PRE[loop] = CURRENT[loop];
			CURRENT[loop].clear();
		}
	}

	for(int a = 0; a < 4; a++){
		for(int i = 0; i < PRE[a].size(); i++){
			if(!PRE[a][i].start_FLG)continue;
			for(int loop = N; loop < 2*N; loop++){
				if(PRE[a][i].code & (1 << loop)){
					printf("Yes\n");
					return;
				}
			}
		}
	}

	printf("No\n");
}

int main(){

	POW[0] = 1;
	for(int i = 1; i < 3*SIZE; i++){

		POW[i] = POW[i-1]*2;
	}

	while(true){
		scanf("%d %d",&N,&num_maze);
		if(N == 0 && num_maze == 0)break;

		func();
	}

	return 0;
}
accuracy: 0.5
time_ms: 210
memory_kb: 3856
final_rank: 16

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define SIZE 15

struct Info{
	Info(int arg_row,int arg_col){
		row = arg_row;
		col = arg_col;
	}
	int row,col;
};

struct Data{
	Data(ll arg_code,bool arg_used){
		code = arg_code;
		used = arg_used;
	}
	bool operator<(const struct Data &arg) const{
		return code < arg.code;
	}
	bool operator==(const struct Data &arg) const{

		return code == arg.code;
	}

	ll code;
	bool used;
};

struct Group{
	Group(){
		code = 0;
		start_FLG = false;
	}

	Group(ll arg_code,bool arg_start_FLG){
		code = arg_code;
		start_FLG = arg_start_FLG;
	}
	bool operator<(const struct Group &arg) const{
		return code < arg.code;
	}
	bool operator==(const struct Group &arg) const{

		return code == arg.code;
	}
	ll code;
	bool start_FLG;
};

int N,num_maze;
int boss[3*SIZE],height[3*SIZE];
ll POW[3*SIZE],CODE[3*SIZE];
int diff_row[4] = {-1,0,0,1},diff_col[4] = {0,-1,1,0};
char input[SIZE][SIZE],used[3*SIZE];
bool visited[SIZE][SIZE],start_array[3*SIZE];
vector<Data> STATES[4][1005];


bool rangeCheck(int row,int col){

	return row >= 0 && row <= N-1 && col >= 0 && col <= N-1;
}

int get_boss(int id){
	if(boss[id] == id)return id;
	else{
		return boss[id] = get_boss(boss[id]);
	}
}

int isSame(int x,int y){
	return get_boss(x) == get_boss(y);
}

void unite(int x,int y){
	int boss_x = get_boss(x);
	int boss_y = get_boss(y);

	//既に同じグループなら何もしない
	if(boss_x == boss_y)return;

	//高さが高い方に吸収する
	if(height[x] > height[y]){

		boss[boss_y] = boss_x;

	}else if(height[x] < height[y]){

		boss[boss_x] = boss_y;

	}else{ //height[x] == height[y]

		boss[boss_y] = boss_x;
		height[x]++;
	}
}

void unite_2(int x,int y){
	int boss_x = get_boss(x);
	int boss_y = get_boss(y);

	//既に同じグループなら何もしない
	if(boss_x == boss_y)return;

	//高さが高い方に吸収する
	if(height[x] > height[y]){

		start_array[boss_x] |= start_array[boss_y];
		boss[boss_y] = boss_x;

	}else if(height[x] < height[y]){

		start_array[boss_y] |= start_array[boss_x];
		boss[boss_x] = boss_y;

	}else{ //height[x] == height[y]

		start_array[boss_x] |= start_array[boss_y];
		boss[boss_y] = boss_x;
		height[x]++;
	}
}

void init(){

	for(int i = 0; i < 2*N; i++){

		boss[i] = i;
		height[i] = 0;
	}

	for(int row = 0; row < N; row++){
		for(int col = 0; col < N; col++){

			visited[row][col] = false;
		}
	}

	for(int i = 0; i < 2*N; i++){

		CODE[i] = 0;
	}
}


void roll_90(char table[SIZE][SIZE]){

	char tmp[SIZE][SIZE];

	for(int row = 0; row < N; row++){
		for(int col = 0; col < N; col++){
			tmp[col][N-1-row] = table[row][col];
		}
	}

	for(int row = 0; row < N; row++){
		for(int col = 0; col < N; col++){
			table[row][col] = tmp[row][col];
		}
	}
}

void func(){

	for(int i = 0; i < 4; i++){
		for(int k = 0; k < num_maze; k++){

			STATES[i][k].clear();
		}
	}

	queue<Info> Q;

	for(int i = 0; i < num_maze; i++){

		for(int row = 0; row < N; row++){
			scanf("%s",input[row]);
		}

		for(int loop = 0; loop < 4; loop++){ //表を回転させ、右端と左端の「到達可能性関係」を調べておく

			roll_90(input);
			init();

			for(int start_row = 0; start_row < N; start_row++){

				if(input[start_row][0] == '#' || visited[start_row][0] == true)continue;

				visited[start_row][0] = true;
				Q.push(Info(start_row,0));

				while(!Q.empty()){

					for(int a = 0; a < 4; a++){

						int adj_row = Q.front().row+diff_row[a];
						int adj_col = Q.front().col+diff_col[a];

						if(rangeCheck(adj_row,adj_col) == false || input[adj_row][adj_col] == '#' ||
								visited[adj_row][adj_col] == true)continue;

						visited[adj_row][adj_col] = true;
						Q.push(Info(adj_row,adj_col));
					}

					Q.pop();
				}

				//★他のstart_rowとのグループ化★
				for(int other_start_row = 0; other_start_row < N; other_start_row++){
					if(other_start_row == start_row)continue;

					if(visited[other_start_row][0]){
						//printf("%d-%dをunite\n",start_row,other_start_row);
						unite(start_row,other_start_row);
					}
				}

				for(int goal_row = 0; goal_row < N; goal_row++){

					if(visited[goal_row][N-1]){
						unite(start_row,N+goal_row);
					}
				}

				for(int k = 0; k < 2*N; k++){
					if(get_boss(k) != get_boss(start_row))continue; //start_rowと同グループのみ計上

					CODE[get_boss(k)] += POW[k];
				}

				for(int k = 0; k < 2*N; k++){

					if(CODE[k] == 0)continue;
					STATES[loop][i].push_back(Data(CODE[k],false));
				}
			}

			for(int goal_row = 0; goal_row < N; goal_row++){ //★★折り返し対策★★

				if(input[goal_row][N-1] == '#' || visited[goal_row][N-1] == true)continue;

				visited[goal_row][N-1] = true;
				Q.push(Info(goal_row,N-1));

				while(!Q.empty()){

					for(int a = 0; a < 4; a++){

						int adj_row = Q.front().row+diff_row[a];
						int adj_col = Q.front().col+diff_col[a];

						if(rangeCheck(adj_row,adj_col) == false || input[adj_row][adj_col] == '#' ||
								visited[adj_row][adj_col] == true)continue;

						visited[adj_row][adj_col] = true;
						Q.push(Info(adj_row,adj_col));
					}

					Q.pop();
				}

				//★他のgoal_rowとのグループ化(左端と接続することはないはず)★
				for(int other_goal_row = 0; other_goal_row < N; other_goal_row++){
					if(other_goal_row == goal_row)continue;

					if(visited[other_goal_row][N-1]){

						unite(N+goal_row,N+other_goal_row);
					}
				}

				for(int k = N; k < 2*N; k++){
					if(get_boss(k) != get_boss(goal_row))continue; //goal_rowと同グループのみ計上

					CODE[get_boss(k)] += POW[k];
				}

				for(int k = N; k < 2*N; k++){

					if(CODE[k] == 0)continue;
					STATES[loop][i].push_back(Data(CODE[k],false));
				}
			}
			sort(STATES[loop][i].begin(),STATES[loop][i].end());
			STATES[loop][i].erase(unique(STATES[loop][i].begin(),STATES[loop][i].end()),STATES[loop][i].end());
		}
	}

	vector<Group> PRE[4],CURRENT[4];

	for(int loop = 0; loop < 4; loop++){

		for(int k = 0; k < STATES[loop][0].size(); k++){ //左端マップの,コードの走査【コードと、start_FLGを紐づける】
			bool start_FLG = false;
			for(int a = 0; a < N; a++){
				if(STATES[loop][0][k].code & (1 << a)){
					start_FLG = true;
					break;
				}
			}
			if(!start_FLG)continue;
			PRE[loop].push_back(Group(STATES[loop][0][k].code,start_FLG));
		}
	}

	vector<ll> work[4];

	for(int i = 1; i < num_maze; i++){

		for(int loop = 0; loop < 4; loop++){

			work[loop].clear();
		}


		for(int loop = 0; loop < 4; loop++){
			//STATES[loop][i]の各要素にNを加え、一時的なコードを作る
			for(int k = 0; k < STATES[loop][i].size(); k++){

				ll tmp_code = 0;

				for(int loop_2 = 0; loop_2 < 2*N; loop_2++){
					if(STATES[loop][i][k].code & (1 << loop_2)){

						tmp_code += POW[loop_2+N];
					}
				}
				work[loop].push_back(tmp_code);
			}
		}

		//コードをマージする
		for(int a_loop = 0; a_loop < 4; a_loop++){//左マップの回転のループ
			for(int b_loop = 0; b_loop < 4; b_loop++){ //右マップの回転のループ

				//UnionFind木を使う
				for(int k = 0; k < 3*N; k++){

					boss[k] = k;
					height[k] = 0;
					start_array[k] = false;
					CODE[k] = 0;
					used[k] = false;
				}

				int parent;

				//左マップの情報の反映
				for(int a = 0; a < PRE[a_loop].size(); a++){

					if(PRE[a_loop][a].start_FLG){ //startを出発している状態ならば、UF木に情報を反映

						for(int k = 0; k < 2*N; k++){
							if(PRE[a_loop][a].code & (1 << k)){
								start_array[k] = true;
							}
						}
					}

					for(int p = 0; p < 2*N; p++){
						if(PRE[a_loop][a].code & (1 << p)){
							used[p] = true;
							parent = p;
						}
					}
					for(int p = 0; p < 2*N; p++){
						if(p == parent)continue;
						if(PRE[a_loop][a].code & (1 << p)){
							used[p] = true;
							unite_2(parent,p);
						}
					}
				}

				//右マップの情報の反映
				for(int b = 0; b < work[b_loop].size(); b++){
					for(int p = N; p < 3*N; p++){
						if(work[b_loop][b] & (1 << p)){
							used[p] = true;
							parent = p;
						}
					}
					for(int p = N; p < 3*N; p++){
						if(p == parent)continue;
						if(work[b_loop][b] & (1 << p)){
							used[p] = true;
							unite_2(parent,p);
						}
					}
				}

				bool FLG = false; //少なくとも1組、左端(スタートと連結)と右端が繋がっているか調べる
				for(int p = 0; p < N; p++){
					for(int q = 2*N; q < 3*N; q++){
						if(get_boss(p) == get_boss(q)){

							FLG = true;
							break;
						}
					}
					if(FLG)break;
				}

				if(!FLG)continue;

				////中間を除きつつ,新しくGroupを作る
				for(int k = 0; k < N; k++){
					if(!used[k])continue;
					CODE[get_boss(k)] += POW[k];
				}
				for(int k = 2*N; k < 3*N; k++){
					if(!used[k])continue;
					CODE[get_boss(k)] += POW[k-N]; //★★元々足してあったNを引く★★
				}

				for(int k = 0; k < 3*N; k++){
					if(CODE[k] == 0)continue;
					CURRENT[a_loop].push_back(Group(CODE[k],start_array[k]));
				}
			}

			sort(CURRENT[a_loop].begin(),CURRENT[a_loop].end());
			CURRENT[a_loop].erase(unique(CURRENT[a_loop].begin(),CURRENT[a_loop].end()),CURRENT[a_loop].end());
		}

		for(int loop = 0; loop < 4; loop++){

			PRE[loop].clear();
			PRE[loop] = CURRENT[loop];
			CURRENT[loop].clear();
		}
	}

	for(int a = 0; a < 4; a++){
		for(int i = 0; i < PRE[a].size(); i++){
			if(!PRE[a][i].start_FLG)continue;
			for(int loop = N; loop < 2*N; loop++){
				if(PRE[a][i].code & (1 << loop)){
					printf("Yes\n");
					return;
				}
			}
		}
	}

	printf("No\n");
}

int main(){

	POW[0] = 1;
	for(int i = 1; i < 3*SIZE; i++){

		POW[i] = POW[i-1]*2;
	}

	while(true){
		scanf("%d %d",&N,&num_maze);
		if(N == 0 && num_maze == 0)break;

		func();
	}

	return 0;
}
accuracy: 0.5
time_ms: 350
memory_kb: 3940
final_rank: 19

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define SIZE 15

struct Info{
	Info(int arg_row,int arg_col){
		row = arg_row;
		col = arg_col;
	}
	int row,col;
};

struct Data{
	Data(ll arg_code,bool arg_used){
		code = arg_code;
		used = arg_used;
	}
	bool operator<(const struct Data &arg) const{
		return code < arg.code;
	}
	bool operator==(const struct Data &arg) const{

		return code == arg.code;
	}

	ll code;
	bool used;
};

struct Group{
	Group(){
		code = 0;
		start_FLG = false;
	}

	Group(ll arg_code,bool arg_start_FLG){
		code = arg_code;
		start_FLG = arg_start_FLG;
	}
	bool operator<(const struct Group &arg) const{
		return code < arg.code;
	}
	bool operator==(const struct Group &arg) const{

		return code == arg.code;
	}
	ll code;
	bool start_FLG;
};

int N,num_maze;
int boss[3*SIZE],height[3*SIZE];
ll POW[3*SIZE],CODE[3*SIZE];
int diff_row[4] = {-1,0,0,1},diff_col[4] = {0,-1,1,0};
char input[SIZE][SIZE],used[3*SIZE];
bool visited[SIZE][SIZE],start_array[3*SIZE];
vector<Data> STATES[4][1005];


bool rangeCheck(int row,int col){

	return row >= 0 && row <= N-1 && col >= 0 && col <= N-1;
}

int get_boss(int id){
	if(boss[id] == id)return id;
	else{
		return boss[id] = get_boss(boss[id]);
	}
}

int isSame(int x,int y){
	return get_boss(x) == get_boss(y);
}

void unite(int x,int y){
	int boss_x = get_boss(x);
	int boss_y = get_boss(y);

	//既に同じグループなら何もしない
	if(boss_x == boss_y)return;

	//高さが高い方に吸収する
	if(height[x] > height[y]){

		boss[boss_y] = boss_x;

	}else if(height[x] < height[y]){

		boss[boss_x] = boss_y;

	}else{ //height[x] == height[y]

		boss[boss_y] = boss_x;
		height[x]++;
	}
}

void unite_2(int x,int y){
	int boss_x = get_boss(x);
	int boss_y = get_boss(y);

	//既に同じグループなら何もしない
	if(boss_x == boss_y)return;

	//高さが高い方に吸収する
	if(height[x] > height[y]){

		start_array[boss_x] |= start_array[boss_y];
		boss[boss_y] = boss_x;

	}else if(height[x] < height[y]){

		start_array[boss_y] |= start_array[boss_x];
		boss[boss_x] = boss_y;

	}else{ //height[x] == height[y]

		start_array[boss_x] |= start_array[boss_y];
		boss[boss_y] = boss_x;
		height[x]++;
	}
}

void init(){

	for(int i = 0; i < 2*N; i++){

		boss[i] = i;
		height[i] = 0;
	}

	for(int row = 0; row < N; row++){
		for(int col = 0; col < N; col++){

			visited[row][col] = false;
		}
	}

	for(int i = 0; i < 2*N; i++){

		CODE[i] = 0;
	}
}


void roll_90(char table[SIZE][SIZE]){

	char tmp[SIZE][SIZE];

	for(int row = 0; row < N; row++){
		for(int col = 0; col < N; col++){
			tmp[col][N-1-row] = table[row][col];
		}
	}

	for(int row = 0; row < N; row++){
		for(int col = 0; col < N; col++){
			table[row][col] = tmp[row][col];
		}
	}
}

void func(){

	for(int i = 0; i < 4; i++){
		for(int k = 0; k < num_maze; k++){

			STATES[i][k].clear();
		}
	}

	queue<Info> Q;

	for(int i = 0; i < num_maze; i++){

		for(int row = 0; row < N; row++){
			scanf("%s",input[row]);
		}

		for(int loop = 0; loop < 4; loop++){ //表を回転させ、右端と左端の「到達可能性関係」を調べておく

			roll_90(input);
			init();

			for(int start_row = 0; start_row < N; start_row++){

				if(input[start_row][0] == '#' || visited[start_row][0] == true)continue;

				visited[start_row][0] = true;
				Q.push(Info(start_row,0));

				while(!Q.empty()){

					for(int a = 0; a < 4; a++){

						int adj_row = Q.front().row+diff_row[a];
						int adj_col = Q.front().col+diff_col[a];

						if(rangeCheck(adj_row,adj_col) == false || input[adj_row][adj_col] == '#' ||
								visited[adj_row][adj_col] == true)continue;

						visited[adj_row][adj_col] = true;
						Q.push(Info(adj_row,adj_col));
					}

					Q.pop();
				}

				//★他のstart_rowとのグループ化★
				for(int other_start_row = 0; other_start_row < N; other_start_row++){
					if(other_start_row == start_row)continue;

					if(visited[other_start_row][0]){
						//printf("%d-%dをunite\n",start_row,other_start_row);
						unite(start_row,other_start_row);
					}
				}

				for(int goal_row = 0; goal_row < N; goal_row++){

					if(visited[goal_row][N-1]){
						unite(start_row,N+goal_row);
					}
				}

				for(int k = 0; k < 2*N; k++){
					if(get_boss(k) != get_boss(start_row))continue; //start_rowと同グループのみ計上

					CODE[get_boss(k)] += POW[k];
				}

				for(int k = 0; k < 2*N; k++){

					if(CODE[k] == 0)continue;
					STATES[loop][i].push_back(Data(CODE[k],false));
				}
			}

			for(int goal_row = 0; goal_row < N; goal_row++){ //★★折り返し対策★★

				if(input[goal_row][N-1] == '#' || visited[goal_row][N-1] == true)continue;

				visited[goal_row][N-1] = true;
				Q.push(Info(goal_row,N-1));

				while(!Q.empty()){

					for(int a = 0; a < 4; a++){

						int adj_row = Q.front().row+diff_row[a];
						int adj_col = Q.front().col+diff_col[a];

						if(rangeCheck(adj_row,adj_col) == false || input[adj_row][adj_col] == '#' ||
								visited[adj_row][adj_col] == true)continue;

						visited[adj_row][adj_col] = true;
						Q.push(Info(adj_row,adj_col));
					}

					Q.pop();
				}

				//★他のgoal_rowとのグループ化(左端と接続することはないはず)★
				for(int other_goal_row = 0; other_goal_row < N; other_goal_row++){
					if(other_goal_row == goal_row)continue;

					if(visited[other_goal_row][N-1]){

						unite(N+goal_row,N+other_goal_row);
					}
				}

				for(int k = N; k < 2*N; k++){
					if(get_boss(k) != get_boss(goal_row))continue; //goal_rowと同グループのみ計上

					CODE[get_boss(k)] += POW[k];
				}

				for(int k = N; k < 2*N; k++){

					if(CODE[k] == 0)continue;
					STATES[loop][i].push_back(Data(CODE[k],false));
				}
			}
			sort(STATES[loop][i].begin(),STATES[loop][i].end());
			STATES[loop][i].erase(unique(STATES[loop][i].begin(),STATES[loop][i].end()),STATES[loop][i].end());
		}
	}

	vector<Group> PRE[4],CURRENT[4];

	for(int loop = 0; loop < 4; loop++){

		for(int k = 0; k < STATES[loop][0].size(); k++){ //左端マップの,コードの走査【コードと、start_FLGを紐づける】
			bool start_FLG = false;
			for(int a = 0; a < N; a++){
				if(STATES[loop][0][k].code & (1 << a)){
					start_FLG = true;
					break;
				}
			}
			if(!start_FLG)continue;
			PRE[loop].push_back(Group(STATES[loop][0][k].code,start_FLG));
		}
	}

	vector<ll> work[4];

	for(int i = 1; i < num_maze; i++){

		for(int loop = 0; loop < 4; loop++){

			work[loop].clear();
		}


		for(int loop = 0; loop < 4; loop++){
			//STATES[loop][i]の各要素にNを加え、一時的なコードを作る
			for(int k = 0; k < STATES[loop][i].size(); k++){

				ll tmp_code = 0;

				for(int loop_2 = 0; loop_2 < 2*N; loop_2++){
					if(STATES[loop][i][k].code & (1 << loop_2)){

						tmp_code += POW[loop_2+N];
					}
				}
				work[loop].push_back(tmp_code);
			}
		}

		//コードをマージする
		for(int a_loop = 0; a_loop < 4; a_loop++){//左マップの回転のループ
			for(int b_loop = 0; b_loop < 4; b_loop++){ //右マップの回転のループ

				//UnionFind木を使う
				for(int k = 0; k < 3*N; k++){

					boss[k] = k;
					height[k] = 0;
					start_array[k] = false;
					CODE[k] = 0;
					used[k] = false;
				}

				int parent;

				//左マップの情報の反映
				for(int a = 0; a < PRE[a_loop].size(); a++){

					if(PRE[a_loop][a].start_FLG){ //startを出発している状態ならば、UF木に情報を反映

						for(int k = 0; k < 2*N; k++){
							if(PRE[a_loop][a].code & (1 << k)){
								start_array[k] = true;
							}
						}
					}

					for(int p = 0; p < 2*N; p++){
						if(PRE[a_loop][a].code & (1 << p)){
							used[p] = true;
							parent = p;
						}
					}
					for(int p = 0; p < 2*N; p++){
						if(p == parent)continue;
						if(PRE[a_loop][a].code & (1 << p)){
							used[p] = true;
							unite_2(parent,p);
						}
					}
				}

				//右マップの情報の反映
				for(int b = 0; b < work[b_loop].size(); b++){
					for(int p = N; p < 3*N; p++){
						if(work[b_loop][b] & (1 << p)){
							used[p] = true;
							parent = p;
						}
					}
					for(int p = N; p < 3*N; p++){
						if(p == parent)continue;
						if(work[b_loop][b] & (1 << p)){
							used[p] = true;
							unite_2(parent,p);
						}
					}
				}

				bool FLG = false; //少なくとも1組、左端(スタートと連結)と右端が繋がっているか調べる
				for(int p = 0; p < N; p++){
					for(int q = 2*N; q < 3*N; q++){
						if(get_boss(p) == get_boss(q) && start_array[p] == true){

							FLG = true;
							break;
						}
					}
					if(FLG)break;
				}

				if(!FLG)continue;

				////中間を除きつつ,新しくGroupを作る
				for(int k = 0; k < N; k++){
					if(!used[k])continue;
					CODE[get_boss(k)] += POW[k];
				}
				for(int k = 2*N; k < 3*N; k++){
					if(!used[k])continue;
					CODE[get_boss(k)] += POW[k-N]; //★★元々足してあったNを引く★★
				}

				for(int k = 0; k < 3*N; k++){
					if(CODE[k] == 0)continue;
					CURRENT[a_loop].push_back(Group(CODE[k],start_array[k]));
				}
			}

			sort(CURRENT[a_loop].begin(),CURRENT[a_loop].end());
			CURRENT[a_loop].erase(unique(CURRENT[a_loop].begin(),CURRENT[a_loop].end()),CURRENT[a_loop].end());
		}

		for(int loop = 0; loop < 4; loop++){

			PRE[loop].clear();
			PRE[loop] = CURRENT[loop];
			CURRENT[loop].clear();
		}
	}

	for(int a = 0; a < 4; a++){
		for(int i = 0; i < PRE[a].size(); i++){
			if(!PRE[a][i].start_FLG)continue;
			for(int loop = N; loop < 2*N; loop++){
				if(PRE[a][i].code & (1 << loop)){
					printf("Yes\n");
					return;
				}
			}
		}
	}

	printf("No\n");
}

int main(){

	POW[0] = 1;
	for(int i = 1; i < 3*SIZE; i++){

		POW[i] = POW[i-1]*2;
	}

	while(true){
		scanf("%d %d",&N,&num_maze);
		if(N == 0 && num_maze == 0)break;

		func();
	}

	return 0;
}
accuracy: 0.5
time_ms: 280
memory_kb: 3868
final_rank: 17

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define SIZE 15

struct Info{
	Info(int arg_row,int arg_col){
		row = arg_row;
		col = arg_col;
	}
	int row,col;
};

struct Data{
	Data(ll arg_code,bool arg_used){
		code = arg_code;
		used = arg_used;
	}
	bool operator<(const struct Data &arg) const{
		return code < arg.code;
	}
	bool operator==(const struct Data &arg) const{

		return code == arg.code;
	}

	ll code;
	bool used;
};

struct Group{
	Group(){
		code = 0;
		start_FLG = false;
	}

	Group(ll arg_code,bool arg_start_FLG){
		code = arg_code;
		start_FLG = arg_start_FLG;
	}
	bool operator<(const struct Group &arg) const{
		return code < arg.code;
	}
	bool operator==(const struct Group &arg) const{

		return code == arg.code;
	}
	ll code;
	bool start_FLG;
};

int N,num_maze;
int boss[3*SIZE],height[3*SIZE];
ll POW[3*SIZE],CODE[3*SIZE];
int diff_row[4] = {-1,0,0,1},diff_col[4] = {0,-1,1,0};
char input[SIZE][SIZE],used[3*SIZE];
bool visited[SIZE][SIZE],start_array[3*SIZE];
vector<Data> STATES[4][1005];


bool rangeCheck(int row,int col){

	return row >= 0 && row <= N-1 && col >= 0 && col <= N-1;
}

int get_boss(int id){
	if(boss[id] == id)return id;
	else{
		return boss[id] = get_boss(boss[id]);
	}
}

int isSame(int x,int y){
	return get_boss(x) == get_boss(y);
}

void unite(int x,int y){
	int boss_x = get_boss(x);
	int boss_y = get_boss(y);

	//既に同じグループなら何もしない
	if(boss_x == boss_y)return;

	//高さが高い方に吸収する
	if(height[x] > height[y]){

		boss[boss_y] = boss_x;

	}else if(height[x] < height[y]){

		boss[boss_x] = boss_y;

	}else{ //height[x] == height[y]

		boss[boss_y] = boss_x;
		height[x]++;
	}
}

void unite_2(int x,int y){
	int boss_x = get_boss(x);
	int boss_y = get_boss(y);

	//既に同じグループなら何もしない
	if(boss_x == boss_y)return;

	//高さが高い方に吸収する
	if(height[x] > height[y]){

		start_array[boss_x] |= start_array[boss_y];
		boss[boss_y] = boss_x;

	}else if(height[x] < height[y]){

		start_array[boss_y] |= start_array[boss_x];
		boss[boss_x] = boss_y;

	}else{ //height[x] == height[y]

		start_array[boss_x] |= start_array[boss_y];
		boss[boss_y] = boss_x;
		height[x]++;
	}
}

void init(){

	for(int i = 0; i < 2*N; i++){

		boss[i] = i;
		height[i] = 0;
	}

	for(int row = 0; row < N; row++){
		for(int col = 0; col < N; col++){

			visited[row][col] = false;
		}
	}

	for(int i = 0; i < 2*N; i++){

		CODE[i] = 0;
	}
}


void roll_90(char table[SIZE][SIZE]){

	char tmp[SIZE][SIZE];

	for(int row = 0; row < N; row++){
		for(int col = 0; col < N; col++){
			tmp[col][N-1-row] = table[row][col];
		}
	}

	for(int row = 0; row < N; row++){
		for(int col = 0; col < N; col++){
			table[row][col] = tmp[row][col];
		}
	}
}

void func(){

	for(int i = 0; i < 4; i++){
		for(int k = 0; k < num_maze; k++){

			STATES[i][k].clear();
		}
	}

	queue<Info> Q;

	for(int i = 0; i < num_maze; i++){

		for(int row = 0; row < N; row++){
			scanf("%s",input[row]);
		}

		for(int loop = 0; loop < 4; loop++){ //表を回転させ、右端と左端の「到達可能性関係」を調べておく

			roll_90(input);
			init();

			for(int start_row = 0; start_row < N; start_row++){

				if(input[start_row][0] == '#' || visited[start_row][0] == true)continue;

				visited[start_row][0] = true;
				Q.push(Info(start_row,0));

				while(!Q.empty()){

					for(int a = 0; a < 4; a++){

						int adj_row = Q.front().row+diff_row[a];
						int adj_col = Q.front().col+diff_col[a];

						if(rangeCheck(adj_row,adj_col) == false || input[adj_row][adj_col] == '#' ||
								visited[adj_row][adj_col] == true)continue;

						visited[adj_row][adj_col] = true;
						Q.push(Info(adj_row,adj_col));
					}

					Q.pop();
				}

				//★他のstart_rowとのグループ化★
				for(int other_start_row = 0; other_start_row < N; other_start_row++){
					if(other_start_row == start_row)continue;

					if(visited[other_start_row][0]){
						//printf("%d-%dをunite\n",start_row,other_start_row);
						unite(start_row,other_start_row);
					}
				}

				for(int goal_row = 0; goal_row < N; goal_row++){

					if(visited[goal_row][N-1]){
						unite(start_row,N+goal_row);
					}
				}

				for(int k = 0; k < 2*N; k++){
					if(get_boss(k) != get_boss(start_row))continue; //start_rowと同グループのみ計上

					CODE[get_boss(k)] += POW[k];
				}

				for(int k = 0; k < 2*N; k++){

					if(CODE[k] == 0)continue;
					STATES[loop][i].push_back(Data(CODE[k],false));
				}
			}

			for(int goal_row = 0; goal_row < N; goal_row++){ //★★折り返し対策★★

				if(input[goal_row][N-1] == '#' || visited[goal_row][N-1] == true)continue;

				visited[goal_row][N-1] = true;
				Q.push(Info(goal_row,N-1));

				while(!Q.empty()){

					for(int a = 0; a < 4; a++){

						int adj_row = Q.front().row+diff_row[a];
						int adj_col = Q.front().col+diff_col[a];

						if(rangeCheck(adj_row,adj_col) == false || input[adj_row][adj_col] == '#' ||
								visited[adj_row][adj_col] == true)continue;

						visited[adj_row][adj_col] = true;
						Q.push(Info(adj_row,adj_col));
					}

					Q.pop();
				}

				//★他のgoal_rowとのグループ化(左端と接続することはないはず)★
				for(int other_goal_row = 0; other_goal_row < N; other_goal_row++){
					if(other_goal_row == goal_row)continue;

					if(visited[other_goal_row][N-1]){

						unite(N+goal_row,N+other_goal_row);
					}
				}

				for(int k = N; k < 2*N; k++){
					if(get_boss(k) != get_boss(goal_row))continue; //goal_rowと同グループのみ計上

					CODE[get_boss(k)] += POW[k];
				}

				for(int k = N; k < 2*N; k++){

					if(CODE[k] == 0)continue;
					STATES[loop][i].push_back(Data(CODE[k],false));
				}
			}
			sort(STATES[loop][i].begin(),STATES[loop][i].end());
			STATES[loop][i].erase(unique(STATES[loop][i].begin(),STATES[loop][i].end()),STATES[loop][i].end());
		}
	}

	vector<Group> PRE[4],CURRENT[4];

	for(int loop = 0; loop < 4; loop++){

		for(int k = 0; k < STATES[loop][0].size(); k++){ //左端マップの,コードの走査【コードと、start_FLGを紐づける】
			bool start_FLG = false;
			for(int a = 0; a < N; a++){
				if(STATES[loop][0][k].code & (1 << a)){
					start_FLG = true;
					break;
				}
			}
			PRE[loop].push_back(Group(STATES[loop][0][k].code,start_FLG));
		}
	}

	vector<ll> work[4];

	for(int i = 1; i < num_maze; i++){

		for(int loop = 0; loop < 4; loop++){

			work[loop].clear();
		}


		for(int loop = 0; loop < 4; loop++){
			//STATES[loop][i]の各要素にNを加え、一時的なコードを作る
			for(int k = 0; k < STATES[loop][i].size(); k++){

				ll tmp_code = 0;

				for(int loop_2 = 0; loop_2 < 2*N; loop_2++){
					if(STATES[loop][i][k].code & (1 << loop_2)){

						tmp_code += POW[loop_2+N];
					}
				}
				work[loop].push_back(tmp_code);
			}
		}

		//コードをマージする
		for(int a_loop = 0; a_loop < 4; a_loop++){//左マップの回転のループ
			for(int b_loop = 0; b_loop < 4; b_loop++){ //右マップの回転のループ

				//UnionFind木を使う
				for(int k = 0; k < 3*N; k++){

					boss[k] = k;
					height[k] = 0;
					start_array[k] = false;
					CODE[k] = 0;
					used[k] = false;
				}

				int parent;

				//左マップの情報の反映
				for(int a = 0; a < PRE[a_loop].size(); a++){

					if(PRE[a_loop][a].start_FLG){ //startを出発している状態ならば、UF木に情報を反映

						for(int k = 0; k < 2*N; k++){
							if(PRE[a_loop][a].code & (1 << k)){
								start_array[k] = true;
							}
						}
					}

					for(int p = 0; p < 2*N; p++){
						if(PRE[a_loop][a].code & (1 << p)){
							used[p] = true;
							parent = p;
						}
					}
					for(int p = 0; p < 2*N; p++){
						if(p == parent)continue;
						if(PRE[a_loop][a].code & (1 << p)){

							unite_2(parent,p);
						}
					}
				}

				//右マップの情報の反映
				for(int b = 0; b < work[b_loop].size(); b++){
					for(int p = N; p < 3*N; p++){
						if(work[b_loop][b] & (1 << p)){
							used[p] = true;
							parent = p;
						}
					}
					for(int p = N; p < 3*N; p++){
						if(p == parent)continue;
						if(work[b_loop][b] & (1 << p)){

							unite_2(parent,p);
						}
					}
				}

				bool FLG = false; //少なくとも1組、左端(スタートと連結)と右端が繋がっているか調べる
				for(int p = 0; p < N; p++){
					for(int q = 2*N; q < 3*N; q++){
						if(get_boss(p) == get_boss(q) && start_array[p] == true){

							FLG = true;
							break;
						}
					}
					if(FLG)break;
				}

				if(!FLG)continue;

				////中間を除きつつ,新しくGroupを作る
				for(int k = 0; k < N; k++){
					if(!used[k])continue;
					CODE[get_boss(k)] += POW[k];
				}
				for(int k = 2*N; k < 3*N; k++){
					if(!used[k])continue;
					CODE[get_boss(k)] += POW[k-N]; //★★元々足してあったNを引く★★
				}

				for(int k = 0; k < 3*N; k++){
					if(CODE[k] == 0)continue;
					CURRENT[a_loop].push_back(Group(CODE[k],start_array[k]));
				}
			}

			sort(CURRENT[a_loop].begin(),CURRENT[a_loop].end());
			CURRENT[a_loop].erase(unique(CURRENT[a_loop].begin(),CURRENT[a_loop].end()),CURRENT[a_loop].end());
		}

		for(int loop = 0; loop < 4; loop++){

			PRE[loop].clear();
			PRE[loop] = CURRENT[loop];
			CURRENT[loop].clear();
		}
	}

	for(int a = 0; a < 4; a++){
		for(int i = 0; i < PRE[a].size(); i++){
			if(!PRE[a][i].start_FLG)continue;
			for(int loop = N; loop < 2*N; loop++){
				if(PRE[a][i].code & (1 << loop)){
					printf("Yes\n");
					return;
				}
			}
		}
	}

	printf("No\n");
}

int main(){

	POW[0] = 1;
	for(int i = 1; i < 3*SIZE; i++){

		POW[i] = POW[i-1]*2;
	}

	while(true){
		scanf("%d %d",&N,&num_maze);
		if(N == 0 && num_maze == 0)break;

		func();
	}

	return 0;
}
accuracy: 0.5
time_ms: 280
memory_kb: 3972
final_rank: 18

code_snippet: #include <bits/stdc++.h>
#define GET_MACRO(_1,_2,_3,_4,_5,_6,_7,_8,NAME,...) NAME
#define pr(...) cerr<< GET_MACRO(__VA_ARGS__,pr8,pr7,pr6,pr5,pr4,pr3,pr2,pr1)(__VA_ARGS__) <<endl
#define pr1(a) (#a)<<"="<<(a)<<" "
#define pr2(a,b) pr1(a)<<pr1(b)
#define pr3(a,b,c) pr1(a)<<pr2(b,c)
#define pr4(a,b,c,d) pr1(a)<<pr3(b,c,d)
#define pr5(a,b,c,d,e) pr1(a)<<pr4(b,c,d,e)
#define pr6(a,b,c,d,e,f) pr1(a)<<pr5(b,c,d,e,f)
#define pr7(a,b,c,d,e,f,g) pr1(a)<<pr6(b,c,d,e,f,g)
#define pr8(a,b,c,d,e,f,g,h) pr1(a)<<pr7(b,c,d,e,f,g,h)
#define prArr(a) {cerr<<(#a)<<"={";int i=0;for(auto t:(a))cerr<<(i++?", ":"")<<t;cerr<<"}"<<endl;}
using namespace std;
using Int = long long;
using _int = int;
using ll = long long;
using Double = long double;
const Int INF = (1LL<<60)+1e9; // ~ 1.15 * 1e18
const Int mod = (1e9)+7;
const Double EPS = 1e-8;
const Double PI = 6.0 * asin((Double)0.5);
using P = pair<Int,Int>;
template<class T> T Max(T &a,T b){return a=max(a,b);}
template<class T> T Min(T &a,T b){return a=min(a,b);}
template<class T1, class T2> ostream& operator<<(ostream& o,pair<T1,T2> p){return o<<"("<<p.first<<","<<p.second<<")";}
template<class T1, class T2, class T3> ostream& operator<<(ostream& o,tuple<T1,T2,T3> t){
  return o<<"("<<get<0>(t)<<","<<get<1>(t)<<","<<get<2>(t)<<")";}
template<class T1, class T2> istream& operator>>(istream& i,pair<T1,T2> &p){return i>>p.first>>p.second;}
template<class T> ostream& operator<<(ostream& o,vector<T> a){Int i=0;for(T t:a)o<<(i++?" ":"")<<t;return o;}
template<class T> istream& operator>>(istream& i,vector<T> &a){for(T &t:a)i>>t;return i;}

class UF{
public:
  int V;
  vector<int> par,rnk,sz;
  UF(){}
  UF(int V):V(V),par(V),rnk(V,0),sz(V,1){for(int i=0;i<V;i++)par[i]=i;}
  
  int find(int x){
    assert(x < V);
    if(par[x]==x)return x;
    return par[x]=find(par[x]);
  }
  
  void unite(int x,int y){
    x=find(x), y=find(y);
    if(x==y)return;
    if(x > y)par[x]=y, sz[y] += sz[x];
    else{
      par[y]=x;
      sz[x] += sz[y];
      if(rnk[x]==rnk[y])rnk[x]++;
    }
  }

  bool same(int x,int y){return find(x)==find(y);}

  int size(int x){return sz[find(x)];}
};

vector<string> rot90(const vector<string> &v){
  int h = v.size(), w = v[0].size();
  vector<string> res(w,string(h,'.'));
  for(int i=0;i<h;i++) for(int j=0;j<w;j++) res[j][h-i-1] = v[i][j];
  return res;
}

int h, w, n;
vector<vector<string> >mp;
int getIdx(int y,int x){return w * (w - 1 - x) + y;}

vector<int> getNext(vector<int> par, vector<string> &mp){

  assert((int)par.size() == h);
  vector<vector<int> > num(h, vector<int>(w));
  for(int i=0;i<h;i++)
    for(int j=0;j<w;j++) num[i][j] = getIdx(i, j) + h + 1;

  for(int i=0;i<h;i++) if(par[i] != -1) num[i][0] = par[i];
  
  UF uf(h * w + h + 1);
  for(int i=0;i<h;i++){
    for(int j=0;j<w;j++){
      if(mp[i][j] == '#') continue;
      if(i + 1 < h && mp[i+1][j] != '#') uf.unite(num[i][j], num[i+1][j]);
      if(j + 1 < w && mp[i][j+1] != '#') uf.unite(num[i][j], num[i][j+1]);
    }
  }

  for(int i=0;i<h;i++)
    for(int j=0;j<w;j++) num[i][j] = uf.find(num[i][j]);
  //for(int i=0;i<h;i++) pr(mp[i]);
  //for(int i=0;i<w;i++) pr(i, num[i]);


  vector<int> res(h, -1);
  vector<int> used(w * h + h + 1, -1);
  int cnt = 1;
  for(int i=0;i<h;i++){
    if(mp[i][w-1] == '#') continue;
    int p = num[i][w-1];
    if(p == 0) res[i] = 0;
    else if(used[p] != -1) res[i] = used[p];
    else res[i] = used[p] = cnt++;
  } 
  return res;
}

int check(vector<int> &par){
  for(int i=0;i<h;i++) if(par[i] == 0) return 1;
  return 0;
}

vector<map<vector<int>, int> >mem;
int dfs(int idx, vector<int> par){
  //pr(idx, par);
  if(check(par) == false) return 0;
  if(idx == n) return 1;
  if(mem[idx].count(par)) return mem[idx][par];
  
  int res = false;
  auto tmp = mp[idx];
  for(int i=0;i<4;i++){
    if(res) break;
    tmp = rot90(tmp);
    auto npar = getNext(par, tmp);
    res |= dfs(idx+1, npar);
  }
  return mem[idx][par] = res;
}

signed main(){
  srand((unsigned)time(NULL));
  cin.tie(0);
  ios_base::sync_with_stdio(0);
  cout << fixed << setprecision(12);
  while(1){
    cin>>h>>n;
    w = h;
    
    if( h == 0 && w == 0) break;
    mp.clear();
    mp.resize(n, vector<string>(h));
    cin>>mp;

    mem.clear();
    mem.resize(n);
    int ans = dfs(0, vector<int>(h, 0));
    cout<<(ans? "Yes":"No")<<endl;
  }
  return 0;
}
accuracy: 1
time_ms: 240
memory_kb: 5204
final_rank: 3

code_snippet: #include <iostream>
#include <vector>
#include <set>
#include <map>
#include <string>
#include <queue>
#include <algorithm>
using namespace std;

#define rep(i,n) for(int i=0;i<n;i++)
int n,m;

vector<vector<string> > s;

class UF {
private:
    int sz; vector<int> par,nrank,size;
public:
    UF(){}
    UF(int node_size){ sz = node_size; par.resize(sz),nrank.resize(sz),size.resize(sz);
        rep(i,sz){ par[i] = i; nrank[i] = 0; size[i] = 1;} }
    int find(int x){ if(par[x] == x){ return x; }else{ return par[x] = find(par[x]); } }
    void unite(int x,int y)
    { x = find(x),y = find(y); if(x == y) return; if(nrank[x] < nrank[y]) swap(x,y);
        par[y] = x; size[x] += size[y]; if(nrank[x] == nrank[y]) nrank[x]++; }
    int query(int x){ x = find(x); return size[x]; }
    bool same(int x,int y){ return find(x) == find(y); }
};


int row(int a){
    return a/n;
}
int col(int a){
    return a%n;
}

int val(int a,int b){
    return a*n+b;
}

vector<set<int> > create(vector<string> &p){
    UF uf(n*n+2);
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            if(p[i][j]=='#'){
                uf.unite(val(i,j),n*n+1);
            }
        }
    }
    for(int i=0;i<n;i++){
        for(int j=0;j<n-1;j++){
            if(p[i][j]=='.'&&p[i][j+1]=='.'){
                uf.unite(val(i,j),val(i,j+1));
            }
        }
    }
    for(int j=0;j<n;j++){
        for(int i=0;i<n-1;i++){
            if(p[i][j]=='.'&&p[i+1][j]=='.'){
                uf.unite(val(i,j),val(i+1,j));
            }
        }
    }
    map<int,set<int> > mp;
    for(int i=0;i<n;i++){
        if(!uf.same(val(i,0),n*n+1)){
            mp[uf.find(val(i,0))].insert(i);
        }
        if(!uf.same(val(i,n-1),n*n+1)){
            mp[uf.find(val(i,n-1))].insert(i+n);
        }
    }
    vector<set<int> > res;
    for(auto x:mp){
        res.push_back(x.second);
    }
    return res;
}

vector<string> rotate(vector<string> &p){
    vector<string> res(n);
    for(int i=n-1;i>=0;i--){
        for(int j=0;j<n;j++){
            res[j].push_back(p[i][j]);
        }
    }
    return res;
}

vector<int>  update(vector<int> &v,vector<set<int> > &st){
    vector<int> res(n,-1);
    int ma = -1;
    for(auto x:v){
        ma = max(ma,x);
    }

    UF uf(2*n+1);
    vector<int>s(n);
    map<int,vector<int> > mp;
    for(int i=0;i<n;i++){
        mp[v[i]].push_back(i);
    }
    for(auto x:mp){
        int tmp =0;
        if(x.first!=-1){
            for(int i=0;i<x.second.size();i++){
                if(i==0){
                    tmp = x.second[i];
                }else{
                    uf.unite(tmp,x.second[i]);
                }
            }
        }
    }
    // for(auto x:st){
    //     for(auto p:x){
    //         cout << p << " ";
    //     }
    //     cout << endl;
    // }
    for(auto x:st){
        bool flag = 1;
        int tmp = 0;
        for(auto p:x){
            if(flag){
                if(p<n){
                    if(v[p]!=-1){
                        tmp = p;
                        flag = 0;
                    }
                }else{
                    tmp = p;
                    flag = 0;
                }
            }else{
                if(p<n){
                    if(v[p]!=-1){
                        uf.unite(tmp,p);
                    }
                }else{
                    uf.unite(tmp,p);
                }
            }
        }
    }
    map<int,int>mi;
    for(int i=0;i<n;i++){
      
            if(v[i]!=-1){
                mi[uf.find(i)] = min(mi[uf.find(i)],v[i]);
            }
    
    }
    // for(int i=0;i<2*n;i++) cout << uf.find(i) <<  " ";
    // cout << endl;
    map<int,int> mp2;
    int cnt = ma  + 1;
    for(int i=n;i<2*n;i++){
        //cout << uf.find(i) << endl;
        if(uf.find(i)<n){
            res[i-n] = mi[uf.find(i)];
        }else{
            if(mp2.find(uf.find(i))==mp2.end()){
                mp2[uf.find(i)] = cnt;
                res[i-n] = cnt;
                cnt++;
            }else{
                res[i-n] = mp2[uf.find(i)];
            }
        }
    }
    vector<int>res2(n);
    map<int,int> tr; 
    int c = 1;
    for(int i=0;i<n;i++){
        if(res[i]==0){
            res[i] = 0;
        }else if(res[i]==-1){
            res2[i] = -1;
        }else if(tr.find(res[i])==tr.end()){
            tr[res[i]] = c;
            res2[i] = c;
            c++;
        }else{
            res2[i] = tr[res[i]];
        }
    }
    // for(auto x:v){
    //     cout << x << " ";
    // }
    // cout << endl;
    // for(auto x:res){
    //     cout << x << " ";
    // }
    // cout << endl;
    return res2;
}


int main(){
    while(cin >> n >> m &&n!=0){
        s.resize(m);
        for(int i=0;i<m;i++){
            s[i].resize(n);
            for(int j=0;j<n;j++){
                cin >> s[i][j];
            }
        }
        vector<int> v(n);
        set<vector<int> > st;
        st.insert(v);
        vector<vector<vector< set<int> > > > reach(m,vector<vector<set<int> > > (4));
        rep(i,m){
            vector<string> a = s[i];
            rep(j,4){
                reach[i][j]=create(a);
                a = rotate(a);
            }
        }
        for(int i=0;i<m;i++){
            set<vector<int> > st2;
            for(auto x:st){
                vector<int> ppp;
                for(int j=0;j<4;j++){
                    ppp = update(x,reach[i][j]);
                    bool insertflag = 0;
                    for(auto u:ppp){
                        if(u==0)insertflag =1;
                    }
                    if(insertflag)st2.insert(ppp);
                   
                    // for(auto y:ppp) cout << y << " ";
                    // cout << endl;
                }
            }
            //cerr << i << " " << st.size() << endl;
            st = st2;
        }
        //cerr << st.size() << endl;
        bool flag = 0;
        for(auto x:st){
            for(auto y:x){
                if(y==0){
                    flag = 1;
                }
            }
        }
        if(flag){
            cout << "Yes" << endl;
        }else{
            cout << "No" << endl;
        }
    }
    return 0;
}
accuracy: 1
time_ms: 800
memory_kb: 7252
final_rank: 11

code_snippet: #include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;

vector<vector<int>>input(int N) {
	vector<vector<int>>v(N,vector<int>(N));
	for (int i = 0; i < N; ++i) {
		string st;cin>>st;
		for (int j = 0; j < N; ++j) {
			v[i][j]=st[j]=='.';
		}
	}
	return v;
}
vector<vector<int>>rotate(vector<vector<int>>v) {
	int N=v.size();
	vector<vector<int>>nv(v.size(),vector<int>(v.size()));
	for (int i = 0; i < N; ++i) {
		for (int j = 0; j < N; ++j) {
			nv[i][j]=v[j][N-1-i];
		}
	}
	return nv;
}
bool operator<(const vector<int>&l, const vector<int>&r) {
	for (int i = 0; i < l.size(); ++i) {
		if(l[i]<r[i])return true;
		else if(l[i]>r[i])return false;
	}
	return false;
}


struct UnionFind {
	vector<int> data;
	UnionFind(int size) : data(size, -1) { }
	bool unionSet(int x, int y) {
		x = root(x); y = root(y);
		if (x != y) {
			if (data[y] < data[x]) swap(x, y);
			data[x] += data[y]; data[y] = x;
		}
		return x != y;
	}
	int root(int x) {
		return data[x] < 0 ? x : data[x] = root(data[x]);
	}
	int size(int x) {
		return -data[root(x)];
	}
};

pair<int, vector<int>>solve(pair<int, vector<int>>p, vector<vector<int>>field) {
	int dx[] = { -1,0,1,0 };
	int dy[] = { 0,1,0,-1 };

	const int start_id=p.first;
	const vector<int> v=p.second;

	int N=field.size();
	UnionFind uf(N*(N+1)+1);

	for (int i = 0; i < N; ++i) {
		if (v[i] == start_id) {
			uf.unionSet(i,N*(N+1));
		}
		for (int j = 0; j < N; ++j) {
			if (v[i] == v[j]) {
				uf.unionSet(i,j);
			}
		}
		if (p.second[i]&&field[i][0]) {
			uf.unionSet(i,i+N);
		}
	}
	for (int y = 0; y < N; ++y) {
		for (int x = 0; x < N; ++x) {
			for (int way = 0; way < 4; ++way) {
				int nx=x+dx[way];
				int ny=y+dy[way];
				if (nx >= 0 && nx < N&&ny >= 0 && ny < N) {
					if(field[y][x]&&field[ny][nx])uf.unionSet(x*N+N+y,nx*N+N+ny);
				}
			}
		}
	}

	vector<int>right_v(N);
	const int right_start=uf.root(N*(N+1));
	for (int i = 0; i < N; ++i) {
		right_v[i]=uf.root(N*N+i);
	}
	
	map<int,int>mp;

	vector<int>right_nv(N);
	int id=1;
	for (int i = 0; i < N; ++i) {
		if (field[i][N - 1]) {
			if (mp.find(right_v[i]) == mp.end()) {
				mp[right_v[i]]=id++;
			}
			right_nv[i]=mp[right_v[i]];
		}
		else {
			right_nv[i]=0;
		}
	}
	if (mp.find(right_start) == mp.end()) {
		return make_pair(-1,right_nv);
	}
	else {
		return make_pair(mp[right_start],right_nv);
	}
}

int main()
{
	while (true) {
		int N,M;cin>>N>>M;
		if(!N)break;
		set<pair<int,vector<int>>>mp;
		mp.emplace(make_pair(1,vector<int>(N,1)));

		for (int i = 0; i < M; ++i) {
			set<pair<int, vector<int>>>n_mp;
			vector<vector<int>>field = input(N);
			for (auto v : mp) {
				for (int way = 0; way < 4; ++way) {
					field=rotate(field);
					auto np=solve(v,field);

					if (np.first == -1) {
						continue;
					}
					n_mp.emplace(np);
				}
			}

			mp=n_mp;
		}

		if (mp.empty()) {
			cout<<"No"<<endl;
		}
		else {
			cout<<"Yes"<<endl;
		}
	}
	return 0;
}
accuracy: 1
time_ms: 590
memory_kb: 3072
final_rank: 6

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef vector<int> vec;
typedef vector<vec> mat;
int dy[]={-1,0,1,0};
int dx[]={0,1,0,-1};
int N,M;
mat mazes[1000];

void rotate(mat &t){
  for(int i=0;i<N;i++)
    for(int j=0;j<N/2;j++)
      swap(t[i][j],t[i][N-1-j]);
  for(int i=0;i<N;i++)
    for(int j=0;j<i;j++)
      swap(t[i][j],t[j][i]);
}

void dfs(vec &t,mat &m,mat &d,int y,int x,int root){
  d[y][x]=root;
  for(int i=0;i<4;i++){
    int ny=y+dy[i];
    int nx=x+dx[i];
    if(ny<0||nx<0||ny>=N||nx>=N)continue;
    if(d[ny][nx]!=-1||m[ny][nx]==1)continue;
    dfs(t,m,d,ny,nx,root);
  }
  
  if(x>0)return;
  if(t[y]==-1)return;
  for(int i=0;i<N;i++){
    if(t[i]!=t[y])continue;
    if(d[i][0]!=-1)continue;
    if(m[i][0]==1)continue;
    dfs(t,m,d,i,0,root);
  }
}

vec reflesh(vec t){
  vec res=t;
  
  map< int ,int > mp;
  for(int i=0;i<N;i++){
    if(res[i]==-1)continue;
    if( mp.count(res[i]) ){
      res[i]=mp[res[i]];
    }else if(res[i]==0){
      
    }else{
      mp[ res[i] ]=0;
      int f=mp.size();
      mp[ res[i] ]=f;
      res[i]=f;
    }
  }
  return res;
}

vec merge(vec t,mat m){
  mat d( N, vec(N,-1) );
  for(int si=0;si<N;si++){
    if(d[si][0]!=-1)continue;
    if(m[si][0]==1)continue;
    if(t[si]==-1)continue;
    if(t[si]!=0)continue;
    dfs(t,m,d,si,0,t[si]);
  }
  
  for(int si=0;si<N;si++){
    if(d[si][N-1]!=-1)continue;
    if(m[si][N-1]==1)continue;
    dfs(t,m,d,si,N-1,N+si);
  }

  vec res(N,-1);
  for(int i=0;i<N;i++){
    res[i]=d[i][N-1];
  }
  res=reflesh(res);
  return res;
}

bool solve(){
  set< vec > dp;
  dp.insert( vec(N,0) );
  for(int i=0;i<M;i++){
    set< vec > nex;

    mat edge=mazes[i];
    for(int i=0;i<4;i++){
      rotate(edge);
      for(vec v:dp){
        nex.insert( merge( v , edge ) );
      }
    }
    
    dp.clear();
    for( vec v : nex ){
      dp.insert(v);
    }
  }

  for(const vec&v:dp)
    for(int i=0;i<(int)v.size();i++)
      if(v[i]==0)return true;
  return false;
}


void input(int id){
  mazes[id].clear();
  mat A( N, vec(N,0) );
  for(int i=0;i<N;i++){
    for(int j=0;j<N;j++){
      char ch;
      cin>>ch;
      A[i][j]=(ch=='#'?1:0);
    }
  }
  mazes[id]=A;
}

int main(){
  while(1){
    cin>>N>>M;
    if(N==0&&M==0)break;
    for(int i=0;i<M;i++){
      input(i);
    }
    cout<< (solve()?"Yes":"No") <<endl;
  }
  return 0;
}
accuracy: 1
time_ms: 990
memory_kb: 4340
final_rank: 9

code_snippet: #include<iostream>
#include<cstdio>
#include<cstring>
#include<cassert>
#include<climits>
#include<vector>
#include<algorithm>
#include<deque>
#include<map>
#include<set>
#include<queue>

#define REP(i,s,n) for(int i=s;i<n;++i)
#define rep(i,n) REP(i,0,n)
#define IINF INT_MAX
#define ALL(x) x.begin(),x.end()

using namespace std;

typedef long long ll;

const string YES = "Yes";
const string NO  = "No";

const int dx[] = {0,1,0,-1};
const int dy[] = {1,0,-1,0};

const bool debug = false;

int N,M;
vector<string> maze[1010];

vector<string> rotate90(vector<string>& piece){
  vector<string> ret;
  int h = piece[0].size(), w = piece.size();
  ret.resize(h);
  for(int i=0;i<h;i++)ret[i].resize(w);
  for(int y=0;y<(int)ret.size();y++){
    for(int x=0;x<(int)ret[0].size();x++){
      ret[y][x] = piece[ret[0].size()-1-x][y];
    }
  }
  return ret;
}

struct Data {
  vector<int> connection, sp_info;
  bool operator < ( const Data &data ) const {
    if( connection != data.connection ) return connection < data.connection;
    return sp_info < data.sp_info;
  }
};

int find(int x,vector<int> &par) {
  if( x == par[x] ) return x;
  return par[x] = find(par[x],par);
}

void unit(int x,int y,vector<int> &par) {
  x = find(x,par), y = find(y,par);
  if( x != y ) par[x] = y;
}

inline bool isValid(int x,int y) { return 0 <= x && x < N && 0 <= y && y < N; }

void compute() {
  // deque<Data> deq;
  set<Data> dp[2];
  // -- initialize -- BEGIN
  rep(i,4) {

    if( debug ) {
      puts("");
      cout << "INITIAL MAZE --" << endl;
      rep(j,N) cout << maze[0][j] << endl;
    }

    vector<int> connection(N,-1); 
    vector<int> sp_info(N,0); 
    vector<int> par(N*N);
    vector<string> &cmaze = maze[0];
    
    rep(j,(int)par.size()) par[j] = j;
    rep(y,N) rep(x,N) if( cmaze[y][x]  == '.') {
      rep(j,4) {
	int nx = x + dx[j], ny = y + dy[j];
	if( !isValid(nx,ny) ) continue;
	if( cmaze[ny][nx] == '.' ) unit(x+y*N,nx+ny*N,par);
      }
    }

    set<int> mp;
    rep(y,N) if( maze[0][y][0] == '.' ) mp.insert(find(y*N,par));
    rep(y,N) if( maze[0][y][N-1] == '.' ) {
      sp_info[y] = mp.count(find(N-1+y*N,par));
      connection[y] = find(N-1+y*N,par);
    }

    if( debug ) {
      puts("");
      cout << "INITIAL connection --" << endl;
      rep(j,(int)connection.size()) {
	cout << "ID : " << j << ", (" << maze[0][j][N-1] << ") : connection -> " << connection[j] << ", sp_info -> " << sp_info[j] << endl;
      }
      puts("");
    }

    dp[0].insert((Data){connection,sp_info});
    maze[0] = rotate90(maze[0]);

  }
  // -- initialize -- END
  
  REP(i,1,M) {
    vector<string> &cmaze = maze[i];
    int cur = i & 1;
    int pre = ( i - 1 ) & 1;
    dp[cur].clear();
    rep(_,4) {

      vector<int> par(N*(N+1));
      rep(j,N*(N+1)) par[j] = j;

      rep(y,N) rep(x,N) if( cmaze[y][x]  == '.') {
	rep(j,4) {
	  int nx = x + dx[j], ny = y + dy[j];
	  if( !isValid(nx,ny) ) continue;
	  if( cmaze[ny][nx] == '.' ) unit(1+x+y*(N+1),1+nx+ny*(N+1),par);
	}
      }      

      for(auto data : dp[pre]) {
	vector<int> npar = par;
	map<int,int> trans;
	rep(y,N) if( data.connection[y] != -1 ) {
	  if( !trans.count(data.connection[y]) ) trans[data.connection[y]] = y * (N+1);
	  npar[y*(N+1)] = trans[data.connection[y]];
	}

	rep(y,N) if( data.connection[y] != -1 && cmaze[y][0] == '.' ) {
	  unit(y*(N+1),1+y*(N+1),npar);
	}
	
	vector<int> connection(N,-1);
	vector<int> sp_info(N,0);

	set<int> mp;
	rep(y,N) if( data.sp_info[y] ) mp.insert(find(y*(N+1),npar));
	rep(y,N) if( cmaze[y][N-1] == '.' ) {
	  sp_info[y] = mp.count(find(N+y*(N+1),npar));
	  connection[y] = find(N+y*(N+1),npar);
	}

	dp[cur].insert((Data){connection,sp_info});
	
      }
      
      cmaze = rotate90(cmaze);
      
    }

  }

  for(auto data : dp[(M-1)&1]) {
    vector<int> &sp_info = data.sp_info;
    rep(i,N) if( sp_info[i] ) { puts(YES.c_str()); return; }
  }
  puts(NO.c_str());
}

int main() {
  while( cin >> N >> M, N|M ) {
    rep(i,M) {
      maze[i].resize(N);
      rep(j,N) cin >> maze[i][j];
    }
    compute();
  }
  return 0;
}
accuracy: 1
time_ms: 590
memory_kb: 4108
final_rank: 7

code_snippet: # include <bits/stdc++.h>
using namespace std;
#define REP(i,n) for(int i=0;i<(n);i++)
typedef long long ll;
typedef vector<int> vi;
 
// uf
int data[1252];
void init(int n){
  REP(i,n)data[i]=-1;
}
int root(int x){
  return data[x]<0?x:(data[x]=root(data[x]));
}
void unite(int x,int y){
  x=root(x);
  y=root(y);
  if(x!=y){
    if(data[x]>data[y])swap(x,y);
    data[x]+=data[y];
    data[y]=x;
  }
}
 
vi calcinfo(vi args){
  unordered_map<int,int> id;
  int tail = 0;
  vi ret = vi(args.size(),0);
  REP(i,args.size()){
    int x = args[i];
    if(!id.count(root(x))){
      id[root(x)] = tail++;
    }
    ret[i] = id[root(x)];
  }
  return ret;
}
 
int n,m;
char maze[1252][25][21];
char tmp[25][21];
vi mazeinfo[1252][4];
 
int main(){
  while(true){
    scanf("%d%d",&n,&m);
    if(n==0 && m==0)break;
    REP(i,m){
      REP(j,n)scanf("%s",maze[i][j]);
    }
    // cerr << "[!] n=" << n << ", m=" << m << endl;
    // n=1
    if(n==1){
      // cerr << "[n==1]" << endl;
      bool ok = true;
      REP(i,m)if(maze[i][0][0]=='#'){
        ok = false;
      }
      puts(ok?"Yes":"No");
      continue;
    }
    // calc mazeinfo
    REP(i,m)REP(rot,4){
      init(n*n);
      REP(j,n)REP(k,n){
        if(maze[i][j][k]!='.')continue;
        if(j<n-1 && maze[i][j+1][k]=='.'){
          unite(j*n+k, (j+1)*n+k);
        }
        if(k<n-1 && maze[i][j][k+1]=='.'){
          unite(j*n+k, j*n+(k+1));
        }
      }
      vi arg;
      REP(x,n)arg.push_back(x*n);
      REP(x,n)arg.push_back(x*n+n-1);
      vi info = calcinfo(arg);
      mazeinfo[i][rot] = info;
      // rotate
      REP(j,n)REP(k,n)tmp[j][k] = maze[i][k][n-1-j];
      REP(j,n)REP(k,n)maze[i][j][k] = tmp[j][k];
    }
    // cerr << "[!] mazeinfo calc end" << endl;
    // dp
    set<vi> S,T;
    S.insert(vi(2*n,0));
    vi infoget;
    REP(i,n)infoget.push_back(i);
    REP(i,n)infoget.push_back(i+2*n);
    REP(i,m){
      T.clear();
      // cerr << "[dp] step=" << i << ", |state|=" << S.size() << endl;
      for(vi V : S){
        REP(r,4){
          vi U = mazeinfo[i][r];
          init(3*n);
          vi id;
          REP(j,2*n){
            if(id.size()==V[j]){
              id.push_back(j);
            }else{
              unite(j,id[V[j]]);
            }
          }
          id.clear();
          REP(j,2*n){
            if(id.size()==U[j]){
              id.push_back(j+n);
            }else{
              unite(j+n,id[U[j]]);
            }
          }
          set<int> sleft;
          REP(j,n)sleft.insert(root(j));
          bool ok = false;
          REP(j,n)if(sleft.count(root(j+2*n))){
            ok = true;
          }
          if(ok){
            T.insert(calcinfo(infoget));
          }
        }
      }
      swap(S,T);
    }
    if(S.size()){
      puts("Yes");
    }else{
      puts("No");
    }
  }
}
accuracy: 1
time_ms: 360
memory_kb: 4232
final_rank: 2