Problem:
Problem F:
ICPC: Intelligent Congruent Partition of Chocolate
The twins named Tatsuya and Kazuya love chocolate.
They have found a bar of their favorite chocolate in a very strange shape.
The chocolate bar looks to have been eaten partially by Mam.
They, of course, claim to eat it and then 
will cut it into two pieces for their portions. 
Since they want to be sure that the chocolate bar is fairly divided, 
they demand that the shapes of the two pieces are
congruent
and that each piece is
connected
.
The chocolate bar consists of many square shaped blocks of chocolate
connected to the adjacent square blocks of chocolate at their edges.
The whole chocolate bar is also connected.
Cutting the chocolate bar along with some edges of square blocks, 
you should help them to divide it into two congruent and connected pieces of
chocolate.  That is, one piece fits into the other
after it is rotated, turned over and moved properly.
Figure F-1: A partially eaten chocolate bar with 18 square blocks of chocolate
For example, there is a partially eaten chocolate bar
with 18 square blocks of chocolate as depicted in Figure F-1.
Cutting it along with some edges of square blocks, 
you get two pieces of chocolate
with 9 square blocks each as depicted in Figure F-2.
Figure F-2: Partitioning of the chocolate bar in Figure F-1
You get two congruent and connected pieces as the result. 
One of them consists of 9 square blocks hatched with horizontal lines 
and the other with vertical lines.
Rotated clockwise with a right angle and turned over on a horizontal line,
the upper piece exactly fits into the lower piece.
Figure F-3: A shape that cannot be partitioned 
into two congruent and connected pieces
Two square blocks touching only at their corners
are regarded as they are not connected to each other.
Figure F-3 is an example shape that cannot be partitioned into
two congruent and connected pieces.
Note that, without the connectivity requirement,
this shape can be partitioned into two congruent pieces
with three squares (Figure F-4).
Figure F-4: Two congruent but disconnected pieces
Your job is to write a program that judges whether a given bar 
of chocolate can be partitioned into such two 
congruent and connected pieces or not.
Input
The input is a sequence of datasets.
The end of the input is indicated by 
a line containing two zeros separated by a space.
Each dataset is formatted as follows.
w h
r
(1, 1)  ...
r
(1,
w
)
r
(2, 1)  ...
r
(2,
w
)
...
r
(
h
, 1)  ...
r
(
h
,
w
)
The integers
w
and
h
are the width and the height of 
a chocolate bar, respectively. 
You may assume 2 ≤
w
≤ 10 and 2 ≤
h
≤ 10.
Each of the following
h
lines consists of
w
digits
delimited by a space.
The digit
r
(
i
,
j
) represents the existence of a square block of
chocolate at the position 
(
i
,
j
) as follows.
'0': There is no chocolate (i.e., already eaten).
'1': There is a square block of chocolate.
You can assume that there are at most 36 square blocks of 
chocolate in the bar, i.e.,
the
...(truncated)

Submitted solutions:

code_snippet: // AOJ #1158 ICPC: Intelligent Congruent Partition of Chocolate
// 2025.3.30

#include <bits/stdc++.h>
using namespace std;
using ull = unsigned long long;

constexpr int dY[4] = {0, 1, 0, -1};
constexpr int dX[4] = {1, 0, -1, 0};

struct State {
    ull m1, m2;
    bool operator==(const State &other) const {
        return m1 == other.m1 && m2 == other.m2;
    }
};

struct StateHash {
    size_t operator()(const State &s) const {
        auto h1 = std::hash<ull>()(s.m1);
        auto h2 = std::hash<ull>()(s.m2);
        return h1 ^ (h2 + 0x9e3779b97f4a7c15ULL + (h1 << 6) + (h1 >> 2));
    }
};

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

    while(true) {
        int w, h;
        cin >> w >> h;
        if(w == 0) break;

        vector<vector<int>> grid(h, vector<int>(w));
        vector<vector<int>> idx(h, vector<int>(w, -1));
        vector<int> Xs, Ys;
        for(int i = 0; i < h; ++i){
            for(int j = 0; j < w; ++j){
                cin >> grid[i][j];
                if(grid[i][j] == 1) {
                    idx[i][j] = Ys.size();
                    Ys.push_back(i);
                    Xs.push_back(j);
                }
            }
        }
        const int n = Xs.size();
        if(n & 1) {
            cout << "NO" << endl;
            continue;
        }

        auto inRange = [&](int y, int x) -> bool {
            return 0 <= y && y < h && 0 <= x && x < w;
        };

        auto calcDY = [&](int mir, int rot, int sdy, int sdx) -> int {
            if(rot == 0)       return sdy;
            else if(rot == 1)  return (mir ? -sdx : sdx);
            else if(rot == 2)  return -sdy;
            else               return (mir ? sdx : -sdx);
        };
        auto calcDX = [&](int mir, int rot, int sdy, int sdx) -> int {
            if(rot == 0)       return (mir ? -sdx : sdx);
            else if(rot == 1)  return sdy;
            else if(rot == 2)  return (mir ? sdx : -sdx);
            else               return -sdy;
        };

        bool ok = false;
        for (int j = 1; j < n && !ok; ++j) {
            for (int rot = 0; rot < 4 && !ok; ++rot) {
                for (int mir = 0; mir < 2 && !ok; ++mir) {
                    unordered_set<State, StateHash> memo;
                    function<bool(ull, ull)> dfs = [&](ull m1, ull m2) -> bool {
                        if (__builtin_popcountll(m1) == n/2) return true;
                        State st { m1, m2 };
                        if(memo.count(st)) return false;
                        memo.insert(st);
                        for (int i = 0; i < n; ++i) {
                            if (!(m1 & (1ULL << i))) continue;
                            int cy = Ys[i], cx = Xs[i];
                            for (int d = 0; d < 4; ++d) {
                                int ny1 = cy + dY[d], nx1 = cx + dX[d];
                                if(!inRange(ny1, nx1)) continue;
                                if(idx[ny1][nx1] == -1) continue;
                                int id1 = idx[ny1][nx1];
                                int relY = ny1 - Ys[0], relX = nx1 - Xs[0];
                                int ny2 = Ys[j] + calcDY(mir, rot, relY, relX);
                                int nx2 = Xs[j] + calcDX(mir, rot, relY, relX);
                                if(!inRange(ny2, nx2)) continue;
                                if(idx[ny2][nx2] == -1) continue;
                                int id2 = idx[ny2][nx2];
                                if(id1 == id2) continue;
                                if ((m1 | m2) & (1ULL << id1)) continue;
                                if ((m1 | m2) & (1ULL << id2)) continue;
                                ull nm1 = m1 | (1ULL << id1);
                                ull nm2 = m2 | (1ULL << id2);
                                if(dfs(nm1, nm2)) return true;
                            }
                        }
                        return false;
                    };
                    ull start_m1 = 1ULL << 0;
                    ull start_m2 = 1ULL << j;
                    if(dfs(start_m1, start_m2)){
                        ok = true;
                        break;
                    }
                }
            }
        }
        cout << (ok ? "YES" : "NO") << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 760
memory_kb: 5256
final_rank: 4

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

#include <unistd.h>

namespace fastio {
static constexpr uint32_t SZ = 1 << 17;
char ibuf[SZ];
char obuf[SZ];
char out[100];
// pointer of ibuf, obuf


uint32_t pil = 0, pir = 0, por = 0;

struct Pre {
    char num[10000][4];
    constexpr Pre() : num() {
        for (int i = 0; i < 10000; i++) {
            int n = i;
            for (int j = 3; j >= 0; j--) {
                num[i][j] = n % 10 | '0';
                n /= 10;
            }
        }
    }
} constexpr pre;

inline void load() {
    memmove(ibuf, ibuf + pil, pir - pil);
    pir = pir - pil + fread(ibuf + pir - pil, 1, SZ - pir + pil, stdin);
    pil = 0;
    if (pir < SZ)
        ibuf[pir++] = '\n';
}

inline void flush() {
    fwrite(obuf, 1, por, stdout);
    por = 0;
}

void rd(char &c) {
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
}

void rd(string &x) {
    x.clear();
    char c;
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
    do {
        x += c;
        if (pil == pir)
            load();
        c = ibuf[pil++];
    } while (!isspace(c));
}

template <typename T> void rd_real(T &x) {
    string s;
    rd(s);
    x = stod(s);
}

template <typename T> void rd_integer(T &x) {
    if (pil + 100 > pir)
        load();
    char c;
    do
        c = ibuf[pil++];
    while (c < '-');
    bool minus = 0;
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (c == '-') {
            minus = 1, c = ibuf[pil++];
        }
    }
    x = 0;
    while ('0' <= c) {
        x = x * 10 + (c & 15), c = ibuf[pil++];
    }
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (minus)
            x = -x;
    }
}

void rd(int &x) {
    rd_integer(x);
}
void rd(ll &x) {
    rd_integer(x);
}
void rd(i128 &x) {
    rd_integer(x);
}
void rd(uint &x) {
    rd_integer(x);
}
void rd(ull &x) {
    rd_integer(x);
}
void rd(u128 &x) {
    rd_integer(x);
}
void rd(double &x) {
    rd_real(x);
}
void rd(long double &x) {
    rd_real(x);
}

template <class T, class U> void rd(pair<T, U> &p) {
    return rd(p.first), rd(p.second);
}
template <size_t N = 0, typename T> void rd_tuple(T &t) {
    if constexpr (N < std::tuple_size<T>::value) {
        auto &x = std::get<N>(t);
        rd(x);
        rd_tuple<N + 1>(t);
    }
}
template <class... T> void rd(tuple<T...> &tpl) {
    rd_tuple(tpl);
}

template <size_t N = 0, typename T> void rd(array<T, N> &x) {
    for (auto &d : x)
        rd(d);
}
template <class T> void rd(vector<T> &x) {
    for (auto &d : x)
        rd(d);
}

void read() {}
template <class H, class... T> void read(H &h, T &...t) {
    rd(h), read(t...);
}

void wt(const char c) {
    if (por == SZ)
        flush();
    obuf[por++] = c;
}
void wt(const string s) {
    for (char c : s)
        wt(c);
}
void wt(const char *s) {
    size_t len = strlen(s);
    for (size_t i = 0; i < len; i++)
        wt(s[i]);
}

template <typename T> void wt_integer(T x) {
    if (por > SZ - 100)
        flush();
    if (x < 0) {
        obuf[por++] = '-', x = -x;
    }
    int outi;
    for (outi = 96; x >= 10000; outi -= 4) {
        memcpy(out + outi, pre.num[x % 10000], 4);
        x /= 10000;
    }
    if (x >= 1000) {
        memcpy(obuf + por, pre.num[x], 4);
        por += 4;
    } else if (x >= 100) {
        memcpy(obuf + por, pre.num[x] + 1, 3);
        por += 3;
    } else if (x >= 10) {
        int q = (x * 103) >> 10;
        obuf[por] = q | '0';
        obuf[por + 1] = (x - q * 10) | '0';
        por += 2;
    } else
        obuf[por++] = x | '0';
    memcpy(obuf + por, out + outi + 4, 96 - outi);
    por += 96 - outi;
}

template <typename T> void wt_real(T x) {
    ostringstream oss;
    oss << fixed << setprecision(15) << double(x);
    string s = oss.str();
    wt(s);
}

void wt(int x) {
    wt_integer(x);
}
void wt(ll x) {
    wt_integer(x);
}
void wt(i128 x) {
    wt_integer(x);
}
void wt(uint x) {
    wt_integer(x);
}
void wt(ull x) {
    wt_integer(x);
}
void wt(u128 x) {
    wt_integer(x);
}
void wt(double x) {
    wt_real(x);
}
void wt(long double x) {
    wt_real(x);
}

template <class T, class U> void wt(const pair<T, U> val) {
    wt(val.first);
    wt(' ');
    wt(val.second);
}
template <size_t N = 0, typename T> void wt_tuple(const T t) {
    if constexpr (N < std::tuple_size<T>::value) {
        if constexpr (N > 0) {
            wt(' ');
        }
        const auto x = std::get<N>(t);
        wt(x);
        wt_tuple<N + 1>(t);
    }
}
template <class... T> void wt(tuple<T...> tpl) {
    wt_tuple(tpl);
}
template <class T, size_t S> void wt(const array<T, S> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}
template <class T> void wt(const vector<T> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}

void print() {
    wt('\n');
}
template <class Head, class... Tail> void print(Head &&head, Tail &&...tail) {
    wt(head);
    if (sizeof...(Tail))
        wt(' ');
    print(forward<Tail>(tail)...);
}
void __attribute__((destructor)) _d() {
    flush();
}
} // namespace fastio


using fastio::flush;
using fastio::print;
using fastio::read;

inline void first(bool i = true) {
    print(i ? "first" : "second");
}
inline void Alice(bool i = true) {
    print(i ? "Alice" : "Bob");
}
inline void Takahashi(bool i = true) {
    print(i ? "Takahashi" : "Aoki");
}
inline void yes(bool i = true) {
    print(i ? "yes" : "no");
}
inline void Yes(bool i = true) {
    print(i ? "Yes" : "No");
}
inline void No() {
    print("No");
}
inline void YES(bool i = true) {
    print(i ? "YES" : "NO");
}
inline void NO() {
    print("NO");
}
inline void Yay(bool i = true) {
    print(i ? "Yay!" : ":(");
}
inline void Possible(bool i = true) {
    print(i ? "Possible" : "Impossible");
}
inline void POSSIBLE(bool i = true) {
    print(i ? "POSSIBLE" : "IMPOSSIBLE");
}

/**
 * @brief Fast IO
 */

int dx[4] = {1,0,-1,0}, dy[4] = {0,1,0,-1};
int N, M, K;
vector<pair<int,int>> P;
vector<ll> G;
clock_t start;

bool Check(ll X) {
    vector<pair<int,int>> L, R;
    int LYMIN = M, LYMAX = 0, RYMIN = M, RYMAX = 0;
    rep(i,0,(int)(P.size())) {
        if (X & (1LL<<i)) L.push_back(P[i]), chmin(LYMIN,P[i].second), chmax(LYMAX,P[i].second);
        else R.push_back(P[i]), chmin(RYMIN,P[i].second), chmax(RYMAX,P[i].second);
    }
    sort(L.begin(), L.end());
    sort(R.begin(), R.end());
    int DLX = L[K-1].first-L[0].first, DRX = R[K-1].first-R[0].first, DLY = LYMAX-LYMIN, DRY = RYMAX-RYMIN;
    if ((DLX+DLY != DRX+DRY) || (abs(DLX-DLY) != abs(DRX-DRY))) return false;
    rep(__,0,2) {
        rep(_,0,4) {
            sort(R.begin(), R.end());
            bool check = true;
            int DX = R[0].first - L[0].first, DY = R[0].second - L[0].second;
            rep(i,1,K) {
                if ((R[i].first - L[i].first != DX) || (R[i].second - L[i].second != DY)) {
                    check = false;
                    break;
                }
            }
            if (check) return true;
            rep(i,0,K) {
                swap(R[i].first, R[i].second);
                R[i].first = -R[i].first;
            }
        }
        rep(i,0,K) R[i].first = -R[i].first;
    }
    return false;
}

bool DFS(int CurL, int CurR, ll L, ll R, ll X) {
    clock_t end = clock();
    const double time = static_cast<double>(end - start) / CLOCKS_PER_SEC;
    if (time > 0.375) return false;
    if (CurL == K) {
        if (Check(L)) return true;
        return false;
    }
    if (X == 0) return false;
    int LOW = lowbit<ll>(X);
    if (DFS(CurL+1,CurR,L|(1LL<<LOW),R,(X|G[LOW])&(~(L|(1LL<<LOW)))&(~R))) return true;
    if (CurR != K) {
        if (DFS(CurL,CurR+1,L,R|(1LL<<LOW),X&(~L)&(~(R|(1LL<<LOW))))) return true;
    }
    return false;
}

int main() {
while(1) {
    cin >> M >> N;
    if (N == 0 && M == 0) return 0;
    vector<vector<int>> A(N,vector<int>(M));
    rep(i,0,N) rep(j,0,M) cin >> A[i][j], A[i][j]--;
    P.clear();
    int Cur = 0;
    rep(i,0,N) {
        rep(j,0,M) {
            if (A[i][j] == 0) {
                A[i][j] = Cur;
                P.push_back({i,j});
                Cur++;
            }
        }
    }
    if (Cur % 2 == 1) {
        cout << "NO" << endl;
        continue;
    }
    G.assign(Cur,0);
    rep(i,0,Cur) {
        int PX = P[i].first, PY = P[i].second;
        rep(j,0,4) {
            int NX = PX+dx[j], NY = PY+dy[j];
            if (0<=NX&&NX<N&&0<=NY&&NY<M) {
                if (A[NX][NY]>=0) G[i] |= (1LL << (A[NX][NY]));
            }
        }
    }
    K = Cur / 2;
    start = clock();
    cout << (DFS(1,0,1,0,G[0]) ? "YES" : "NO") << endl;
}
}
accuracy: 1
time_ms: 5700
memory_kb: 3424
final_rank: 6

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

#include <unistd.h>

namespace fastio {
static constexpr uint32_t SZ = 1 << 17;
char ibuf[SZ];
char obuf[SZ];
char out[100];
// pointer of ibuf, obuf


uint32_t pil = 0, pir = 0, por = 0;

struct Pre {
    char num[10000][4];
    constexpr Pre() : num() {
        for (int i = 0; i < 10000; i++) {
            int n = i;
            for (int j = 3; j >= 0; j--) {
                num[i][j] = n % 10 | '0';
                n /= 10;
            }
        }
    }
} constexpr pre;

inline void load() {
    memmove(ibuf, ibuf + pil, pir - pil);
    pir = pir - pil + fread(ibuf + pir - pil, 1, SZ - pir + pil, stdin);
    pil = 0;
    if (pir < SZ)
        ibuf[pir++] = '\n';
}

inline void flush() {
    fwrite(obuf, 1, por, stdout);
    por = 0;
}

void rd(char &c) {
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
}

void rd(string &x) {
    x.clear();
    char c;
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
    do {
        x += c;
        if (pil == pir)
            load();
        c = ibuf[pil++];
    } while (!isspace(c));
}

template <typename T> void rd_real(T &x) {
    string s;
    rd(s);
    x = stod(s);
}

template <typename T> void rd_integer(T &x) {
    if (pil + 100 > pir)
        load();
    char c;
    do
        c = ibuf[pil++];
    while (c < '-');
    bool minus = 0;
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (c == '-') {
            minus = 1, c = ibuf[pil++];
        }
    }
    x = 0;
    while ('0' <= c) {
        x = x * 10 + (c & 15), c = ibuf[pil++];
    }
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (minus)
            x = -x;
    }
}

void rd(int &x) {
    rd_integer(x);
}
void rd(ll &x) {
    rd_integer(x);
}
void rd(i128 &x) {
    rd_integer(x);
}
void rd(uint &x) {
    rd_integer(x);
}
void rd(ull &x) {
    rd_integer(x);
}
void rd(u128 &x) {
    rd_integer(x);
}
void rd(double &x) {
    rd_real(x);
}
void rd(long double &x) {
    rd_real(x);
}

template <class T, class U> void rd(pair<T, U> &p) {
    return rd(p.first), rd(p.second);
}
template <size_t N = 0, typename T> void rd_tuple(T &t) {
    if constexpr (N < std::tuple_size<T>::value) {
        auto &x = std::get<N>(t);
        rd(x);
        rd_tuple<N + 1>(t);
    }
}
template <class... T> void rd(tuple<T...> &tpl) {
    rd_tuple(tpl);
}

template <size_t N = 0, typename T> void rd(array<T, N> &x) {
    for (auto &d : x)
        rd(d);
}
template <class T> void rd(vector<T> &x) {
    for (auto &d : x)
        rd(d);
}

void read() {}
template <class H, class... T> void read(H &h, T &...t) {
    rd(h), read(t...);
}

void wt(const char c) {
    if (por == SZ)
        flush();
    obuf[por++] = c;
}
void wt(const string s) {
    for (char c : s)
        wt(c);
}
void wt(const char *s) {
    size_t len = strlen(s);
    for (size_t i = 0; i < len; i++)
        wt(s[i]);
}

template <typename T> void wt_integer(T x) {
    if (por > SZ - 100)
        flush();
    if (x < 0) {
        obuf[por++] = '-', x = -x;
    }
    int outi;
    for (outi = 96; x >= 10000; outi -= 4) {
        memcpy(out + outi, pre.num[x % 10000], 4);
        x /= 10000;
    }
    if (x >= 1000) {
        memcpy(obuf + por, pre.num[x], 4);
        por += 4;
    } else if (x >= 100) {
        memcpy(obuf + por, pre.num[x] + 1, 3);
        por += 3;
    } else if (x >= 10) {
        int q = (x * 103) >> 10;
        obuf[por] = q | '0';
        obuf[por + 1] = (x - q * 10) | '0';
        por += 2;
    } else
        obuf[por++] = x | '0';
    memcpy(obuf + por, out + outi + 4, 96 - outi);
    por += 96 - outi;
}

template <typename T> void wt_real(T x) {
    ostringstream oss;
    oss << fixed << setprecision(15) << double(x);
    string s = oss.str();
    wt(s);
}

void wt(int x) {
    wt_integer(x);
}
void wt(ll x) {
    wt_integer(x);
}
void wt(i128 x) {
    wt_integer(x);
}
void wt(uint x) {
    wt_integer(x);
}
void wt(ull x) {
    wt_integer(x);
}
void wt(u128 x) {
    wt_integer(x);
}
void wt(double x) {
    wt_real(x);
}
void wt(long double x) {
    wt_real(x);
}

template <class T, class U> void wt(const pair<T, U> val) {
    wt(val.first);
    wt(' ');
    wt(val.second);
}
template <size_t N = 0, typename T> void wt_tuple(const T t) {
    if constexpr (N < std::tuple_size<T>::value) {
        if constexpr (N > 0) {
            wt(' ');
        }
        const auto x = std::get<N>(t);
        wt(x);
        wt_tuple<N + 1>(t);
    }
}
template <class... T> void wt(tuple<T...> tpl) {
    wt_tuple(tpl);
}
template <class T, size_t S> void wt(const array<T, S> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}
template <class T> void wt(const vector<T> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}

void print() {
    wt('\n');
}
template <class Head, class... Tail> void print(Head &&head, Tail &&...tail) {
    wt(head);
    if (sizeof...(Tail))
        wt(' ');
    print(forward<Tail>(tail)...);
}
void __attribute__((destructor)) _d() {
    flush();
}
} // namespace fastio


using fastio::flush;
using fastio::print;
using fastio::read;

inline void first(bool i = true) {
    print(i ? "first" : "second");
}
inline void Alice(bool i = true) {
    print(i ? "Alice" : "Bob");
}
inline void Takahashi(bool i = true) {
    print(i ? "Takahashi" : "Aoki");
}
inline void yes(bool i = true) {
    print(i ? "yes" : "no");
}
inline void Yes(bool i = true) {
    print(i ? "Yes" : "No");
}
inline void No() {
    print("No");
}
inline void YES(bool i = true) {
    print(i ? "YES" : "NO");
}
inline void NO() {
    print("NO");
}
inline void Yay(bool i = true) {
    print(i ? "Yay!" : ":(");
}
inline void Possible(bool i = true) {
    print(i ? "Possible" : "Impossible");
}
inline void POSSIBLE(bool i = true) {
    print(i ? "POSSIBLE" : "IMPOSSIBLE");
}

/**
 * @brief Fast IO
 */

int dx[4] = {1,0,-1,0}, dy[4] = {0,1,0,-1};
int N, M, K;
vector<pair<int,int>> P;
vector<ll> G;
clock_t start;

bool Check(ll X) {
    vector<pair<int,int>> L, R;
    int LYMIN = M, LYMAX = 0, RYMIN = M, RYMAX = 0;
    rep(i,0,(int)(P.size())) {
        if (X & (1LL<<i)) L.push_back(P[i]), chmin(LYMIN,P[i].second), chmax(LYMAX,P[i].second);
        else R.push_back(P[i]), chmin(RYMIN,P[i].second), chmax(RYMAX,P[i].second);
    }
    sort(L.begin(), L.end());
    sort(R.begin(), R.end());
    int DLX = L[K-1].first-L[0].first, DRX = R[K-1].first-R[0].first, DLY = LYMAX-LYMIN, DRY = RYMAX-RYMIN;
    if ((DLX+DLY != DRX+DRY) || (abs(DLX-DLY) != abs(DRX-DRY))) return false;
    rep(__,0,2) {
        rep(_,0,4) {
            sort(R.begin(), R.end());
            bool check = true;
            int DX = R[0].first - L[0].first, DY = R[0].second - L[0].second;
            rep(i,1,K) {
                if ((R[i].first - L[i].first != DX) || (R[i].second - L[i].second != DY)) {
                    check = false;
                    break;
                }
            }
            if (check) return true;
            rep(i,0,K) {
                swap(R[i].first, R[i].second);
                R[i].first = -R[i].first;
            }
        }
        rep(i,0,K) R[i].first = -R[i].first;
    }
    return false;
}

bool DFS(int CurL, int CurR, ll L, ll R, ll X) {
    clock_t end = clock();
    const double time = static_cast<double>(end - start) / CLOCKS_PER_SEC;
    if (time > 0.6) return false;
    if (CurL == K) {
        if (Check(L)) return true;
        return false;
    }
    if (X == 0) return false;
    int LOW = lowbit<ll>(X);
    if (DFS(CurL+1,CurR,L|(1LL<<LOW),R,(X|G[LOW])&(~(L|(1LL<<LOW)))&(~R))) return true;
    if (CurR != K) {
        if (DFS(CurL,CurR+1,L,R|(1LL<<LOW),X&(~L)&(~(R|(1LL<<LOW))))) return true;
    }
    return false;
}

int main() {
while(1) {
    cin >> M >> N;
    if (N == 0 && M == 0) return 0;
    vector<vector<int>> A(N,vector<int>(M));
    rep(i,0,N) rep(j,0,M) cin >> A[i][j], A[i][j]--;
    P.clear();
    int Cur = 0;
    rep(i,0,N) {
        rep(j,0,M) {
            if (A[i][j] == 0) {
                A[i][j] = Cur;
                P.push_back({i,j});
                Cur++;
            }
        }
    }
    if (Cur % 2 == 1) {
        cout << "NO" << endl;
        continue;
    }
    G.assign(Cur,0);
    rep(i,0,Cur) {
        int PX = P[i].first, PY = P[i].second;
        rep(j,0,4) {
            int NX = PX+dx[j], NY = PY+dy[j];
            if (0<=NX&&NX<N&&0<=NY&&NY<M) {
                if (A[NX][NY]>=0) G[i] |= (1LL << (A[NX][NY]));
            }
        }
    }
    K = Cur / 2;
    start = clock();
    cout << (DFS(1,0,1,0,G[0]) ? "YES" : "NO") << endl;
}
}
accuracy: 1
time_ms: 7970
memory_kb: 3504
final_rank: 10

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

#include <unistd.h>

namespace fastio {
static constexpr uint32_t SZ = 1 << 17;
char ibuf[SZ];
char obuf[SZ];
char out[100];
// pointer of ibuf, obuf


uint32_t pil = 0, pir = 0, por = 0;

struct Pre {
    char num[10000][4];
    constexpr Pre() : num() {
        for (int i = 0; i < 10000; i++) {
            int n = i;
            for (int j = 3; j >= 0; j--) {
                num[i][j] = n % 10 | '0';
                n /= 10;
            }
        }
    }
} constexpr pre;

inline void load() {
    memmove(ibuf, ibuf + pil, pir - pil);
    pir = pir - pil + fread(ibuf + pir - pil, 1, SZ - pir + pil, stdin);
    pil = 0;
    if (pir < SZ)
        ibuf[pir++] = '\n';
}

inline void flush() {
    fwrite(obuf, 1, por, stdout);
    por = 0;
}

void rd(char &c) {
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
}

void rd(string &x) {
    x.clear();
    char c;
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
    do {
        x += c;
        if (pil == pir)
            load();
        c = ibuf[pil++];
    } while (!isspace(c));
}

template <typename T> void rd_real(T &x) {
    string s;
    rd(s);
    x = stod(s);
}

template <typename T> void rd_integer(T &x) {
    if (pil + 100 > pir)
        load();
    char c;
    do
        c = ibuf[pil++];
    while (c < '-');
    bool minus = 0;
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (c == '-') {
            minus = 1, c = ibuf[pil++];
        }
    }
    x = 0;
    while ('0' <= c) {
        x = x * 10 + (c & 15), c = ibuf[pil++];
    }
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (minus)
            x = -x;
    }
}

void rd(int &x) {
    rd_integer(x);
}
void rd(ll &x) {
    rd_integer(x);
}
void rd(i128 &x) {
    rd_integer(x);
}
void rd(uint &x) {
    rd_integer(x);
}
void rd(ull &x) {
    rd_integer(x);
}
void rd(u128 &x) {
    rd_integer(x);
}
void rd(double &x) {
    rd_real(x);
}
void rd(long double &x) {
    rd_real(x);
}

template <class T, class U> void rd(pair<T, U> &p) {
    return rd(p.first), rd(p.second);
}
template <size_t N = 0, typename T> void rd_tuple(T &t) {
    if constexpr (N < std::tuple_size<T>::value) {
        auto &x = std::get<N>(t);
        rd(x);
        rd_tuple<N + 1>(t);
    }
}
template <class... T> void rd(tuple<T...> &tpl) {
    rd_tuple(tpl);
}

template <size_t N = 0, typename T> void rd(array<T, N> &x) {
    for (auto &d : x)
        rd(d);
}
template <class T> void rd(vector<T> &x) {
    for (auto &d : x)
        rd(d);
}

void read() {}
template <class H, class... T> void read(H &h, T &...t) {
    rd(h), read(t...);
}

void wt(const char c) {
    if (por == SZ)
        flush();
    obuf[por++] = c;
}
void wt(const string s) {
    for (char c : s)
        wt(c);
}
void wt(const char *s) {
    size_t len = strlen(s);
    for (size_t i = 0; i < len; i++)
        wt(s[i]);
}

template <typename T> void wt_integer(T x) {
    if (por > SZ - 100)
        flush();
    if (x < 0) {
        obuf[por++] = '-', x = -x;
    }
    int outi;
    for (outi = 96; x >= 10000; outi -= 4) {
        memcpy(out + outi, pre.num[x % 10000], 4);
        x /= 10000;
    }
    if (x >= 1000) {
        memcpy(obuf + por, pre.num[x], 4);
        por += 4;
    } else if (x >= 100) {
        memcpy(obuf + por, pre.num[x] + 1, 3);
        por += 3;
    } else if (x >= 10) {
        int q = (x * 103) >> 10;
        obuf[por] = q | '0';
        obuf[por + 1] = (x - q * 10) | '0';
        por += 2;
    } else
        obuf[por++] = x | '0';
    memcpy(obuf + por, out + outi + 4, 96 - outi);
    por += 96 - outi;
}

template <typename T> void wt_real(T x) {
    ostringstream oss;
    oss << fixed << setprecision(15) << double(x);
    string s = oss.str();
    wt(s);
}

void wt(int x) {
    wt_integer(x);
}
void wt(ll x) {
    wt_integer(x);
}
void wt(i128 x) {
    wt_integer(x);
}
void wt(uint x) {
    wt_integer(x);
}
void wt(ull x) {
    wt_integer(x);
}
void wt(u128 x) {
    wt_integer(x);
}
void wt(double x) {
    wt_real(x);
}
void wt(long double x) {
    wt_real(x);
}

template <class T, class U> void wt(const pair<T, U> val) {
    wt(val.first);
    wt(' ');
    wt(val.second);
}
template <size_t N = 0, typename T> void wt_tuple(const T t) {
    if constexpr (N < std::tuple_size<T>::value) {
        if constexpr (N > 0) {
            wt(' ');
        }
        const auto x = std::get<N>(t);
        wt(x);
        wt_tuple<N + 1>(t);
    }
}
template <class... T> void wt(tuple<T...> tpl) {
    wt_tuple(tpl);
}
template <class T, size_t S> void wt(const array<T, S> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}
template <class T> void wt(const vector<T> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}

void print() {
    wt('\n');
}
template <class Head, class... Tail> void print(Head &&head, Tail &&...tail) {
    wt(head);
    if (sizeof...(Tail))
        wt(' ');
    print(forward<Tail>(tail)...);
}
void __attribute__((destructor)) _d() {
    flush();
}
} // namespace fastio


using fastio::flush;
using fastio::print;
using fastio::read;

inline void first(bool i = true) {
    print(i ? "first" : "second");
}
inline void Alice(bool i = true) {
    print(i ? "Alice" : "Bob");
}
inline void Takahashi(bool i = true) {
    print(i ? "Takahashi" : "Aoki");
}
inline void yes(bool i = true) {
    print(i ? "yes" : "no");
}
inline void Yes(bool i = true) {
    print(i ? "Yes" : "No");
}
inline void No() {
    print("No");
}
inline void YES(bool i = true) {
    print(i ? "YES" : "NO");
}
inline void NO() {
    print("NO");
}
inline void Yay(bool i = true) {
    print(i ? "Yay!" : ":(");
}
inline void Possible(bool i = true) {
    print(i ? "Possible" : "Impossible");
}
inline void POSSIBLE(bool i = true) {
    print(i ? "POSSIBLE" : "IMPOSSIBLE");
}

/**
 * @brief Fast IO
 */

int dx[4] = {1,0,-1,0}, dy[4] = {0,1,0,-1};
int N, M, K;
vector<pair<int,int>> P;
vector<ll> G;
clock_t start;

bool Check(ll X) {
    vector<pair<int,int>> L, R;
    int LYMIN = M, LYMAX = 0, RYMIN = M, RYMAX = 0;
    rep(i,0,(int)(P.size())) {
        if (X & (1LL<<i)) L.push_back(P[i]), chmin(LYMIN,P[i].second), chmax(LYMAX,P[i].second);
        else R.push_back(P[i]), chmin(RYMIN,P[i].second), chmax(RYMAX,P[i].second);
    }
    sort(L.begin(), L.end());
    sort(R.begin(), R.end());
    int DLX = L[K-1].first-L[0].first, DRX = R[K-1].first-R[0].first, DLY = LYMAX-LYMIN, DRY = RYMAX-RYMIN;
    if ((DLX+DLY != DRX+DRY) || (abs(DLX-DLY) != abs(DRX-DRY))) return false;
    rep(__,0,2) {
        rep(_,0,4) {
            sort(R.begin(), R.end());
            bool check = true;
            int DX = R[0].first - L[0].first, DY = R[0].second - L[0].second;
            rep(i,1,K) {
                if ((R[i].first - L[i].first != DX) || (R[i].second - L[i].second != DY)) {
                    check = false;
                    break;
                }
            }
            if (check) return true;
            rep(i,0,K) {
                swap(R[i].first, R[i].second);
                R[i].first = -R[i].first;
            }
        }
        rep(i,0,K) R[i].first = -R[i].first;
    }
    return false;
}

bool DFS(int CurL, int CurR, ll L, ll R, ll X) {
    clock_t end = clock();
    const double time = static_cast<double>(end - start) / CLOCKS_PER_SEC;
    if (time > 0.375) return false;
    if (CurL == K) {
        if (Check(L)) return true;
        return false;
    }
    if (X == 0) return false;
    int LOW = lowbit<ll>(X);
    if (DFS(CurL+1,CurR,L|(1LL<<LOW),R,(X|G[LOW])&(~(L|(1LL<<LOW)))&(~R))) return true;
    if (CurR != K) {
        if (DFS(CurL,CurR+1,L,R|(1LL<<LOW),X&(~L)&(~(R|(1LL<<LOW))))) return true;
    }
    return false;
}

int main() {
while(1) {
    cin >> M >> N;
    if (N == 0 && M == 0) return 0;
    vector<vector<int>> A(N,vector<int>(M));
    rep(i,0,N) rep(j,0,M) cin >> A[i][j], A[i][j]--;
    P.clear();
    int Cur = 0;
    rep(i,0,N) {
        rep(j,0,M) {
            if (A[i][j] == 0) {
                A[i][j] = Cur;
                P.push_back({i,j});
                Cur++;
            }
        }
    }
    if (Cur % 2 == 1) {
        cout << "NO" << endl;
        continue;
    }
    G.assign(Cur,0);
    rep(i,0,Cur) {
        int PX = P[i].first, PY = P[i].second;
        rep(j,0,4) {
            int NX = PX+dx[j], NY = PY+dy[j];
            if (0<=NX&&NX<N&&0<=NY&&NY<M) {
                if (A[NX][NY]>=0) G[i] |= (1LL << (A[NX][NY]));
            }
        }
    }
    K = Cur / 2;
    start = clock();
    cout << (DFS(1,0,1,0,G[0]) ? "YES" : "NO") << endl;
}
}
accuracy: 1
time_ms: 5710
memory_kb: 3200
final_rank: 5

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

#include <unistd.h>

namespace fastio {
static constexpr uint32_t SZ = 1 << 17;
char ibuf[SZ];
char obuf[SZ];
char out[100];
// pointer of ibuf, obuf


uint32_t pil = 0, pir = 0, por = 0;

struct Pre {
    char num[10000][4];
    constexpr Pre() : num() {
        for (int i = 0; i < 10000; i++) {
            int n = i;
            for (int j = 3; j >= 0; j--) {
                num[i][j] = n % 10 | '0';
                n /= 10;
            }
        }
    }
} constexpr pre;

inline void load() {
    memmove(ibuf, ibuf + pil, pir - pil);
    pir = pir - pil + fread(ibuf + pir - pil, 1, SZ - pir + pil, stdin);
    pil = 0;
    if (pir < SZ)
        ibuf[pir++] = '\n';
}

inline void flush() {
    fwrite(obuf, 1, por, stdout);
    por = 0;
}

void rd(char &c) {
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
}

void rd(string &x) {
    x.clear();
    char c;
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
    do {
        x += c;
        if (pil == pir)
            load();
        c = ibuf[pil++];
    } while (!isspace(c));
}

template <typename T> void rd_real(T &x) {
    string s;
    rd(s);
    x = stod(s);
}

template <typename T> void rd_integer(T &x) {
    if (pil + 100 > pir)
        load();
    char c;
    do
        c = ibuf[pil++];
    while (c < '-');
    bool minus = 0;
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (c == '-') {
            minus = 1, c = ibuf[pil++];
        }
    }
    x = 0;
    while ('0' <= c) {
        x = x * 10 + (c & 15), c = ibuf[pil++];
    }
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (minus)
            x = -x;
    }
}

void rd(int &x) {
    rd_integer(x);
}
void rd(ll &x) {
    rd_integer(x);
}
void rd(i128 &x) {
    rd_integer(x);
}
void rd(uint &x) {
    rd_integer(x);
}
void rd(ull &x) {
    rd_integer(x);
}
void rd(u128 &x) {
    rd_integer(x);
}
void rd(double &x) {
    rd_real(x);
}
void rd(long double &x) {
    rd_real(x);
}

template <class T, class U> void rd(pair<T, U> &p) {
    return rd(p.first), rd(p.second);
}
template <size_t N = 0, typename T> void rd_tuple(T &t) {
    if constexpr (N < std::tuple_size<T>::value) {
        auto &x = std::get<N>(t);
        rd(x);
        rd_tuple<N + 1>(t);
    }
}
template <class... T> void rd(tuple<T...> &tpl) {
    rd_tuple(tpl);
}

template <size_t N = 0, typename T> void rd(array<T, N> &x) {
    for (auto &d : x)
        rd(d);
}
template <class T> void rd(vector<T> &x) {
    for (auto &d : x)
        rd(d);
}

void read() {}
template <class H, class... T> void read(H &h, T &...t) {
    rd(h), read(t...);
}

void wt(const char c) {
    if (por == SZ)
        flush();
    obuf[por++] = c;
}
void wt(const string s) {
    for (char c : s)
        wt(c);
}
void wt(const char *s) {
    size_t len = strlen(s);
    for (size_t i = 0; i < len; i++)
        wt(s[i]);
}

template <typename T> void wt_integer(T x) {
    if (por > SZ - 100)
        flush();
    if (x < 0) {
        obuf[por++] = '-', x = -x;
    }
    int outi;
    for (outi = 96; x >= 10000; outi -= 4) {
        memcpy(out + outi, pre.num[x % 10000], 4);
        x /= 10000;
    }
    if (x >= 1000) {
        memcpy(obuf + por, pre.num[x], 4);
        por += 4;
    } else if (x >= 100) {
        memcpy(obuf + por, pre.num[x] + 1, 3);
        por += 3;
    } else if (x >= 10) {
        int q = (x * 103) >> 10;
        obuf[por] = q | '0';
        obuf[por + 1] = (x - q * 10) | '0';
        por += 2;
    } else
        obuf[por++] = x | '0';
    memcpy(obuf + por, out + outi + 4, 96 - outi);
    por += 96 - outi;
}

template <typename T> void wt_real(T x) {
    ostringstream oss;
    oss << fixed << setprecision(15) << double(x);
    string s = oss.str();
    wt(s);
}

void wt(int x) {
    wt_integer(x);
}
void wt(ll x) {
    wt_integer(x);
}
void wt(i128 x) {
    wt_integer(x);
}
void wt(uint x) {
    wt_integer(x);
}
void wt(ull x) {
    wt_integer(x);
}
void wt(u128 x) {
    wt_integer(x);
}
void wt(double x) {
    wt_real(x);
}
void wt(long double x) {
    wt_real(x);
}

template <class T, class U> void wt(const pair<T, U> val) {
    wt(val.first);
    wt(' ');
    wt(val.second);
}
template <size_t N = 0, typename T> void wt_tuple(const T t) {
    if constexpr (N < std::tuple_size<T>::value) {
        if constexpr (N > 0) {
            wt(' ');
        }
        const auto x = std::get<N>(t);
        wt(x);
        wt_tuple<N + 1>(t);
    }
}
template <class... T> void wt(tuple<T...> tpl) {
    wt_tuple(tpl);
}
template <class T, size_t S> void wt(const array<T, S> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}
template <class T> void wt(const vector<T> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}

void print() {
    wt('\n');
}
template <class Head, class... Tail> void print(Head &&head, Tail &&...tail) {
    wt(head);
    if (sizeof...(Tail))
        wt(' ');
    print(forward<Tail>(tail)...);
}
void __attribute__((destructor)) _d() {
    flush();
}
} // namespace fastio


using fastio::flush;
using fastio::print;
using fastio::read;

inline void first(bool i = true) {
    print(i ? "first" : "second");
}
inline void Alice(bool i = true) {
    print(i ? "Alice" : "Bob");
}
inline void Takahashi(bool i = true) {
    print(i ? "Takahashi" : "Aoki");
}
inline void yes(bool i = true) {
    print(i ? "yes" : "no");
}
inline void Yes(bool i = true) {
    print(i ? "Yes" : "No");
}
inline void No() {
    print("No");
}
inline void YES(bool i = true) {
    print(i ? "YES" : "NO");
}
inline void NO() {
    print("NO");
}
inline void Yay(bool i = true) {
    print(i ? "Yay!" : ":(");
}
inline void Possible(bool i = true) {
    print(i ? "Possible" : "Impossible");
}
inline void POSSIBLE(bool i = true) {
    print(i ? "POSSIBLE" : "IMPOSSIBLE");
}

/**
 * @brief Fast IO
 */

int dx[4] = {1,0,-1,0}, dy[4] = {0,1,0,-1};
int N, M, K;
vector<pair<int,int>> P;
vector<ll> G;
clock_t start;

bool Check(ll X) {
    vector<pair<int,int>> L, R;
    int LYMIN = M, LYMAX = 0, RYMIN = M, RYMAX = 0;
    rep(i,0,(int)(P.size())) {
        if (X & (1LL<<i)) L.push_back(P[i]), chmin(LYMIN,P[i].second), chmax(LYMAX,P[i].second);
        else R.push_back(P[i]), chmin(RYMIN,P[i].second), chmax(RYMAX,P[i].second);
    }
    sort(L.begin(), L.end());
    sort(R.begin(), R.end());
    int DLX = L[K-1].first-L[0].first, DRX = R[K-1].first-R[0].first, DLY = LYMAX-LYMIN, DRY = RYMAX-RYMIN;
    if ((DLX+DLY != DRX+DRY) || (abs(DLX-DLY) != abs(DRX-DRY))) return false;
    rep(__,0,2) {
        rep(_,0,4) {
            sort(R.begin(), R.end());
            bool check = true;
            int DX = R[0].first - L[0].first, DY = R[0].second - L[0].second;
            rep(i,1,K) {
                if ((R[i].first - L[i].first != DX) || (R[i].second - L[i].second != DY)) {
                    check = false;
                    break;
                }
            }
            if (check) return true;
            rep(i,0,K) {
                swap(R[i].first, R[i].second);
                R[i].first = -R[i].first;
            }
        }
        rep(i,0,K) R[i].first = -R[i].first;
    }
    return false;
}

bool DFS(int CurL, int CurR, ll L, ll R, ll X) {
    clock_t end = clock();
    const double time = static_cast<double>(end - start) / CLOCKS_PER_SEC;
    if (time > 0.4) return false;
    if (CurL == K) {
        if (Check(L)) return true;
        return false;
    }
    if (X == 0) return false;
    int LOW = lowbit<ll>(X);
    if (DFS(CurL+1,CurR,L|(1LL<<LOW),R,(X|G[LOW])&(~(L|(1LL<<LOW)))&(~R))) return true;
    if (CurR != K) {
        if (DFS(CurL,CurR+1,L,R|(1LL<<LOW),X&(~L)&(~(R|(1LL<<LOW))))) return true;
    }
    return false;
}

int main() {
while(1) {
    cin >> M >> N;
    if (N == 0 && M == 0) return 0;
    vector<vector<int>> A(N,vector<int>(M));
    rep(i,0,N) rep(j,0,M) cin >> A[i][j], A[i][j]--;
    P.clear();
    int Cur = 0;
    rep(i,0,N) {
        rep(j,0,M) {
            if (A[i][j] == 0) {
                A[i][j] = Cur;
                P.push_back({i,j});
                Cur++;
            }
        }
    }
    if (Cur % 2 == 1) {
        cout << "NO" << endl;
        continue;
    }
    G.assign(Cur,0);
    rep(i,0,Cur) {
        int PX = P[i].first, PY = P[i].second;
        rep(j,0,4) {
            int NX = PX+dx[j], NY = PY+dy[j];
            if (0<=NX&&NX<N&&0<=NY&&NY<M) {
                if (A[NX][NY]>=0) G[i] |= (1LL << (A[NX][NY]));
            }
        }
    }
    K = Cur / 2;
    start = clock();
    cout << (DFS(1,0,1,0,G[0]) ? "YES" : "NO") << endl;
}
}
accuracy: 1
time_ms: 5980
memory_kb: 3432
final_rank: 7

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

#include <unistd.h>

namespace fastio {
static constexpr uint32_t SZ = 1 << 17;
char ibuf[SZ];
char obuf[SZ];
char out[100];
// pointer of ibuf, obuf


uint32_t pil = 0, pir = 0, por = 0;

struct Pre {
    char num[10000][4];
    constexpr Pre() : num() {
        for (int i = 0; i < 10000; i++) {
            int n = i;
            for (int j = 3; j >= 0; j--) {
                num[i][j] = n % 10 | '0';
                n /= 10;
            }
        }
    }
} constexpr pre;

inline void load() {
    memmove(ibuf, ibuf + pil, pir - pil);
    pir = pir - pil + fread(ibuf + pir - pil, 1, SZ - pir + pil, stdin);
    pil = 0;
    if (pir < SZ)
        ibuf[pir++] = '\n';
}

inline void flush() {
    fwrite(obuf, 1, por, stdout);
    por = 0;
}

void rd(char &c) {
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
}

void rd(string &x) {
    x.clear();
    char c;
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
    do {
        x += c;
        if (pil == pir)
            load();
        c = ibuf[pil++];
    } while (!isspace(c));
}

template <typename T> void rd_real(T &x) {
    string s;
    rd(s);
    x = stod(s);
}

template <typename T> void rd_integer(T &x) {
    if (pil + 100 > pir)
        load();
    char c;
    do
        c = ibuf[pil++];
    while (c < '-');
    bool minus = 0;
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (c == '-') {
            minus = 1, c = ibuf[pil++];
        }
    }
    x = 0;
    while ('0' <= c) {
        x = x * 10 + (c & 15), c = ibuf[pil++];
    }
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (minus)
            x = -x;
    }
}

void rd(int &x) {
    rd_integer(x);
}
void rd(ll &x) {
    rd_integer(x);
}
void rd(i128 &x) {
    rd_integer(x);
}
void rd(uint &x) {
    rd_integer(x);
}
void rd(ull &x) {
    rd_integer(x);
}
void rd(u128 &x) {
    rd_integer(x);
}
void rd(double &x) {
    rd_real(x);
}
void rd(long double &x) {
    rd_real(x);
}

template <class T, class U> void rd(pair<T, U> &p) {
    return rd(p.first), rd(p.second);
}
template <size_t N = 0, typename T> void rd_tuple(T &t) {
    if constexpr (N < std::tuple_size<T>::value) {
        auto &x = std::get<N>(t);
        rd(x);
        rd_tuple<N + 1>(t);
    }
}
template <class... T> void rd(tuple<T...> &tpl) {
    rd_tuple(tpl);
}

template <size_t N = 0, typename T> void rd(array<T, N> &x) {
    for (auto &d : x)
        rd(d);
}
template <class T> void rd(vector<T> &x) {
    for (auto &d : x)
        rd(d);
}

void read() {}
template <class H, class... T> void read(H &h, T &...t) {
    rd(h), read(t...);
}

void wt(const char c) {
    if (por == SZ)
        flush();
    obuf[por++] = c;
}
void wt(const string s) {
    for (char c : s)
        wt(c);
}
void wt(const char *s) {
    size_t len = strlen(s);
    for (size_t i = 0; i < len; i++)
        wt(s[i]);
}

template <typename T> void wt_integer(T x) {
    if (por > SZ - 100)
        flush();
    if (x < 0) {
        obuf[por++] = '-', x = -x;
    }
    int outi;
    for (outi = 96; x >= 10000; outi -= 4) {
        memcpy(out + outi, pre.num[x % 10000], 4);
        x /= 10000;
    }
    if (x >= 1000) {
        memcpy(obuf + por, pre.num[x], 4);
        por += 4;
    } else if (x >= 100) {
        memcpy(obuf + por, pre.num[x] + 1, 3);
        por += 3;
    } else if (x >= 10) {
        int q = (x * 103) >> 10;
        obuf[por] = q | '0';
        obuf[por + 1] = (x - q * 10) | '0';
        por += 2;
    } else
        obuf[por++] = x | '0';
    memcpy(obuf + por, out + outi + 4, 96 - outi);
    por += 96 - outi;
}

template <typename T> void wt_real(T x) {
    ostringstream oss;
    oss << fixed << setprecision(15) << double(x);
    string s = oss.str();
    wt(s);
}

void wt(int x) {
    wt_integer(x);
}
void wt(ll x) {
    wt_integer(x);
}
void wt(i128 x) {
    wt_integer(x);
}
void wt(uint x) {
    wt_integer(x);
}
void wt(ull x) {
    wt_integer(x);
}
void wt(u128 x) {
    wt_integer(x);
}
void wt(double x) {
    wt_real(x);
}
void wt(long double x) {
    wt_real(x);
}

template <class T, class U> void wt(const pair<T, U> val) {
    wt(val.first);
    wt(' ');
    wt(val.second);
}
template <size_t N = 0, typename T> void wt_tuple(const T t) {
    if constexpr (N < std::tuple_size<T>::value) {
        if constexpr (N > 0) {
            wt(' ');
        }
        const auto x = std::get<N>(t);
        wt(x);
        wt_tuple<N + 1>(t);
    }
}
template <class... T> void wt(tuple<T...> tpl) {
    wt_tuple(tpl);
}
template <class T, size_t S> void wt(const array<T, S> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}
template <class T> void wt(const vector<T> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}

void print() {
    wt('\n');
}
template <class Head, class... Tail> void print(Head &&head, Tail &&...tail) {
    wt(head);
    if (sizeof...(Tail))
        wt(' ');
    print(forward<Tail>(tail)...);
}
void __attribute__((destructor)) _d() {
    flush();
}
} // namespace fastio


using fastio::flush;
using fastio::print;
using fastio::read;

inline void first(bool i = true) {
    print(i ? "first" : "second");
}
inline void Alice(bool i = true) {
    print(i ? "Alice" : "Bob");
}
inline void Takahashi(bool i = true) {
    print(i ? "Takahashi" : "Aoki");
}
inline void yes(bool i = true) {
    print(i ? "yes" : "no");
}
inline void Yes(bool i = true) {
    print(i ? "Yes" : "No");
}
inline void No() {
    print("No");
}
inline void YES(bool i = true) {
    print(i ? "YES" : "NO");
}
inline void NO() {
    print("NO");
}
inline void Yay(bool i = true) {
    print(i ? "Yay!" : ":(");
}
inline void Possible(bool i = true) {
    print(i ? "Possible" : "Impossible");
}
inline void POSSIBLE(bool i = true) {
    print(i ? "POSSIBLE" : "IMPOSSIBLE");
}

/**
 * @brief Fast IO
 */

int dx[4] = {1,0,-1,0}, dy[4] = {0,1,0,-1};
int N, M, K;
vector<pair<int,int>> P;
vector<ll> G;
clock_t start;

bool Check(ll X) {
    vector<pair<int,int>> L, R;
    int LYMIN = M, LYMAX = 0, RYMIN = M, RYMAX = 0;
    rep(i,0,(int)(P.size())) {
        if (X & (1LL<<i)) L.push_back(P[i]), chmin(LYMIN,P[i].second), chmax(LYMAX,P[i].second);
        else R.push_back(P[i]), chmin(RYMIN,P[i].second), chmax(RYMAX,P[i].second);
    }
    sort(L.begin(), L.end());
    sort(R.begin(), R.end());
    int DLX = L[K-1].first-L[0].first, DRX = R[K-1].first-R[0].first, DLY = LYMAX-LYMIN, DRY = RYMAX-RYMIN;
    if ((DLX+DLY != DRX+DRY) || (abs(DLX-DLY) != abs(DRX-DRY))) return false;
    rep(__,0,2) {
        rep(_,0,4) {
            sort(R.begin(), R.end());
            bool check = true;
            int DX = R[0].first - L[0].first, DY = R[0].second - L[0].second;
            rep(i,1,K) {
                if ((R[i].first - L[i].first != DX) || (R[i].second - L[i].second != DY)) {
                    check = false;
                    break;
                }
            }
            if (check) return true;
            rep(i,0,K) {
                swap(R[i].first, R[i].second);
                R[i].first = -R[i].first;
            }
        }
        rep(i,0,K) R[i].first = -R[i].first;
    }
    return false;
}

bool DFS(int CurL, int CurR, ll L, ll R, ll X) {
    clock_t end = clock();
    const double time = static_cast<double>(end - start) / CLOCKS_PER_SEC;
    if (time > 0.5) return false;
    if (CurL == K) {
        if (Check(L)) return true;
        return false;
    }
    if (X == 0) return false;
    int LOW = lowbit<ll>(X);
    if (DFS(CurL+1,CurR,L|(1LL<<LOW),R,(X|G[LOW])&(~(L|(1LL<<LOW)))&(~R))) return true;
    if (CurR != K) {
        if (DFS(CurL,CurR+1,L,R|(1LL<<LOW),X&(~L)&(~(R|(1LL<<LOW))))) return true;
    }
    return false;
}

int main() {
while(1) {
    cin >> M >> N;
    if (N == 0 && M == 0) return 0;
    vector<vector<int>> A(N,vector<int>(M));
    rep(i,0,N) rep(j,0,M) cin >> A[i][j], A[i][j]--;
    P.clear();
    int Cur = 0;
    rep(i,0,N) {
        rep(j,0,M) {
            if (A[i][j] == 0) {
                A[i][j] = Cur;
                P.push_back({i,j});
                Cur++;
            }
        }
    }
    if (Cur % 2 == 1) {
        cout << "NO" << endl;
        continue;
    }
    G.assign(Cur,0);
    rep(i,0,Cur) {
        int PX = P[i].first, PY = P[i].second;
        rep(j,0,4) {
            int NX = PX+dx[j], NY = PY+dy[j];
            if (0<=NX&&NX<N&&0<=NY&&NY<M) {
                if (A[NX][NY]>=0) G[i] |= (1LL << (A[NX][NY]));
            }
        }
    }
    K = Cur / 2;
    start = clock();
    cout << (DFS(1,0,1,0,G[0]) ? "YES" : "NO") << endl;
}
}
accuracy: 1
time_ms: 6970
memory_kb: 3240
final_rank: 8

code_snippet: #line 2 "cp-library/src/cp-template.hpp"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using uint = unsigned int;
using ull  = unsigned long long;
using i32 = int;
using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128_t;
template < class T > bool chmin(T& a, T b) { if(a > b) { a = b; return true; } return false; }
template < class T > bool chmax(T& a, T b) { if(a < b) { a = b; return true; } return false; }
template < class T, class U > T ceil (T x, U y) { return (x > 0 ? (x + y - 1) / y :           x / y); }
template < class T, class U > T floor(T x, U y) { return (x > 0 ?           x / y : (x - y + 1) / y); }
int popcnt(i32 x) { return __builtin_popcount(x); }
int popcnt(u32 x) { return __builtin_popcount(x); }
int popcnt(i64 x) { return __builtin_popcountll(x); }
int popcnt(u64 x) { return __builtin_popcountll(x); }

#line 2 "cp-library/src/utility/rep_itr.hpp"
template < class T > struct itr_rep {
    T i, d;
    constexpr itr_rep(const T i) noexcept : i(i), d(1) {}
    constexpr itr_rep(const T i, const T d) noexcept : i(i), d(d) {}
    void operator++() noexcept { i += d; }
    constexpr int operator*() const noexcept { return i; }
    constexpr bool operator!=(const itr_rep x) const noexcept { return d > 0 ? i < x.i : i > x.i; }
};

template < class T > struct rep {
    const itr_rep< T > s, t;
    constexpr rep(const T t) noexcept : s(0), t(t) {}
    constexpr rep(const T s, const T t) noexcept : s(s), t(t) {}
    constexpr rep(const T s, const T t, const T d) noexcept : s(s, d), t(t, d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};

template < class T > struct revrep {
    const itr_rep < T > s, t;
    constexpr revrep(const T t) noexcept : s(t - 1, -1), t(-1, -1) {}
    constexpr revrep(const T s, const T t) noexcept : s(t - 1, -1), t(s - 1, -1) {}
    constexpr revrep(const T s, const T t, const T d) noexcept : s(t - 1, -d), t(s - 1, -d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};
#line 3 "cp-library/src/utility/io.hpp"

/* 128bit integer */
istream& operator>>(istream& is, i128& x) {
    std::string s; is >> s;
    int pm = (s[0] == '-');
    x = 0;
    for(int i : rep(pm, int(s.size()))) x = x * 10 + (s[i] - '0');
    if(pm) x *= -1;
    return is;
}
ostream& operator<<(ostream& os, const i128& x) {
    if(x == 0) return os << '0';
    i128 y = x;
    if(y < 0) { os << '-'; y *= -1; }
    std::vector<int> ny;
    while(y > 0) { ny.push_back(y % 10); y /= 10; }
    for(int i : revrep(ny.size())) os << ny[i];
    return os;
}

template < class S, class T > istream& operator>>(istream& is,       std::pair< S, T >& x) { is >> x.first        >> x.second; return is; }
template < class S, class T > ostream& operator<<(ostream& os, const std::pair< S, T >& x) { os << x.first << " " << x.second; return os; }

namespace scanner {
    struct sca {
        template < class T > operator T() {
            T s; std::cin >> s; return s;
        }
    };
    struct vec {
        int n;
        vec(int n) : n(n) {}
        template < class T > operator std::vector< T >() {
            std::vector< T > v(n);
            for(T& x : v) std::cin >> x;
            return v;
        }
    };
    struct mat {
        int h, w;
        mat(int h, int w) : h(h), w(w) {}
        template < class T > operator std::vector< std::vector< T > >() {
            std::vector m(h, std::vector< T >(w));
            for(std::vector< T >& v : m) for(T& x : v) std::cin >> x;
            return m;
        }
    };
    struct speedup {
        speedup() {
            std::cin.tie(0);
            std::ios::sync_with_stdio(0);
        }
    } speedup_instance;
}
scanner::sca in() { return scanner::sca(); }
scanner::vec in(int n) { return scanner::vec(n); }
scanner::mat in(int h, int w) { return scanner::mat(h, w); }

namespace printer {
    void precision(int d) { std::cout << std::fixed << std::setprecision(d); }
    void flush() { std::cout.flush(); }
}

template < class T >
ostream& operator<<(ostream& os, const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) { os << a[i]; if(i != n - 1) os << ' '; }
    return os;
}

int print() { std::cout << '\n'; return 0; }
template < class head, class... tail > int print(head&& h, tail&&... t) {
    std::cout << h; if(sizeof...(tail)) std::cout << ' ';
    return print(std::forward<tail>(t)...);
}
template < class T > int print_n(const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) std::cout << a[i] << "\n";
    return 0;
}


#line 2 "cp-library/src/utility/key_val.hpp"

template < class K, class V >
struct key_val {
    K key; V val;
    key_val() {}
    key_val(K key, V val) : key(key), val(val) {}
    template < std::size_t Index >
    std::tuple_element_t< Index, key_val >& get() {
        if constexpr (Index == 0) return key;
        if constexpr (Index == 1) return val;
    }
};

namespace std {

template < class K, class V > struct tuple_size < key_val< K, V > > : integral_constant< size_t, 2 > {};
template < class K, class V > struct tuple_element < 0, key_val< K, V > > { using type = K; };
template < class K, class V > struct tuple_element < 1, key_val< K, V > > { using type = V; };

}
#line 2 "cp-library/src/utility/vec_op.hpp"
template < class T > key_val< int, T > max_of(const vector< T >& a) {
    int i = std::max_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class T > key_val< int, T > min_of(const vector< T >& a) {
    int i = std::min_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class S, class T > S sum_of(const vector< T >& a) {
    S sum = 0;
    for(const T x : a) sum += x;
    return sum;
}
template < class S, class T > vector< S > freq_of(const vector< T >& a, T L, T R) {
    vector< S > res(R - L, S(0));
    for(const T x : a) res[x - L] += 1;
    return res;
}
template < class S, class T > struct prefix_sum {
    vector< S > s;
    prefix_sum(const vector< T >& a) : s(a) {
        s.insert(s.begin(), S(0));
        for(int i : rep(a.size())) s[i + 1] += s[i];
    }
    // [L, R)
    S sum(int L, int R) { return s[R] - s[L]; }
};
#line 3 "cp-library/src/utility/heap.hpp"

template < class T > using heap_min = std::priority_queue< T, std::vector< T >, std::greater< T > >;
template < class T > using heap_max = std::priority_queue< T, std::vector< T >, std::less< T > >;

#line 27 "cp-library/src/cp-template.hpp"

#line 1 "cp-library/src/algorithm/bin_search.hpp"
template < class T, class F >
T bin_search(T ok, T ng, F f) {
    while(abs(ng - ok) > 1) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}

template < class T, class F >
T bin_search_real(T ok, T ng, F f, int step = 80) {
    while(step--) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}
#line 2 "cp-library/src/algorithm/argsort.hpp"

template < class T > std::vector< int > argsort(const std::vector< T > &a) {
    std::vector< int > ids((int)a.size());
    std::iota(ids.begin(), ids.end(), 0);
    std::sort(ids.begin(), ids.end(), [&](int i, int j) {
        return a[i] < a[j] || (a[i] == a[j] && i < j);
    });
    return ids;
}
#line 1 "macro.hpp"
namespace macro {

using size_type = int;
template < class container > void  sort(container& a) { std::sort(std:: begin(a), std:: end(a)); }
template < class container > void rsort(container& a) { std::sort(std::rbegin(a), std::rend(a)); }
template < class container > void reverse(container& a) { std::reverse(std::begin(a), std::end(a)); }
template < class container > void unique(container& a) {
    std::sort(std::begin(a), std::end(a));
    a.erase(std::unique(std::begin(a), std::end(a)), std::end(a));
}
template < class container > container  sorted(const container& a) { container b = a;  sort(b); return std::move(b); }
template < class container > container rsorted(const container& a) { container b = a; rsort(b); return std::move(b); }
template < class container, class compare > void sort(container& a, const compare& cmp) { std::sort(std::begin(a), std::end(a), cmp); }
template < class container, class compare > container sorted(const container& a, const compare& cmp) { container b = a; sort(b, cmp); return std::move(b); }
template < class container, class value > size_type lower_bound(const container& a, const value& x) { return std::lower_bound(std::begin(a), std::end(a), x) - std::begin(a); }
template < class container, class value > size_type upper_bound(const container& a, const value& x) { return std::upper_bound(std::begin(a), std::end(a), x) - std::begin(a); }

const std::vector<std::pair<size_type, size_type>> dir4 = { {+1,  0}, {-1,  0}, { 0, +1}, { 0, -1} };
const std::vector<std::pair<size_type, size_type>> dir8 = { {-1, -1}, {-1,  0}, {-1, +1}, { 0, -1}, { 0, +1}, {+1, -1}, {+1,  0}, {+1, +1} };

#ifdef _DEBUG
#define debug(x) std::cout << "[" << __LINE__ << "] " << #x << ": " << x << std::endl
#else
#define debug(x)
#endif

template < class container > void concat(container& a, const container& b) {
    a.insert(std::end(a), std::begin(b), std::end(b));
}
std::vector<size_type> iota(const size_type n) {
    std::vector<size_type> I(n);
    std::iota(std::begin(I), std::end(I), 0);
    return I;
}
template < class container > std::vector<size_type> sort_idx(const container& a) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return a[i] < a[j] or (a[i] == a[j] and i < j); });
    return I;
}
template < class container, class compare > std::vector<size_type> sort_idx(const container& a, const compare& cmp) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return cmp(a[i], a[j]) or (a[i] == a[j] and i < j); });
    return std::move(I);
}

struct grid {
    using size_type = int;
    size_type H, W;
    grid(const size_type H, const size_type W) : H(H), W(W) {}
    bool contains(const size_type i, const size_type j) {
        return 0 <= i and i < H and 0 <= j and j < W;
    }
};

using f64 = long double;

template < class T > vector< T >& operator++(vector< T >& a) { for(T& x : a) x++; return a; }
template < class T > vector< T >& operator--(vector< T >& a) { for(T& x : a) x--; return a; }
template < class T > vector< T >  operator++(vector< T >& a, signed) { vector< T > res = a; for(T& x : a) x++; return res; }
template < class T > vector< T >  operator--(vector< T >& a, signed) { vector< T > res = a; for(T& x : a) x--; return res; }

} // namespace macro

using namespace macro;
#line 3 "A.cpp"

bool solve(int w, int h) {
    vector<vector<int>> a = in(h, w);
    const int n = [&] {
        int cnt = 0;
        for(int i : rep(h)) for(int j : rep(w)) cnt += a[i][j];
        return cnt;
    }();
    if(n % 2 == 1) return false;

    // fix rot&rev --> dfs

    vector<int> sx = {0, 1, 0, -1};
    vector<int> sy = {1, 0, -1, 0};
    auto [tx, ty] = make_pair(sx, sy);

    for(int rev_ : rep(2)) {
        for(int rot_ : rep(4)) {
            for(int si : rep(h)) for(int sj : rep(w)) if(a[si][sj]) {
                for(int ti : rep(h)) for(int tj : rep(w)) if(a[ti][tj] and make_pair(ti, tj) != make_pair(si, sj)) {

                    vector s(h, vector(w, 0));
                    vector t(h, vector(w, 0));
                    int sn = 0, tn = 0;
                    auto dfs = [&](auto self, int si, int sj, int ti, int tj) -> bool {
                        sn += (++s[si][sj]);
                        tn += (++t[ti][tj]);
                        if(sn == n / 2 and tn == n / 2) return true;
                        for(int d : rep(4)) {
                            int nsi = si + sx[d], nsj = sj + sy[d];
                            int nti = ti + tx[d], ntj = tj + ty[d];
                            if(not(0 <= nsi and nsi < h and 0 <= nsj and nsj < w)) continue;
                            if(not(0 <= nti and nti < h and 0 <= ntj and ntj < w)) continue;
                            if(make_pair(nsi, nsj) == make_pair(nti, ntj)) continue;
                            if(not(a[nsi][nsj] and a[nti][ntj])) continue;
                            if(not(s[nti][ntj] == 0 and t[nsi][nsj] == 0)) continue;
                            if(not(s[nsi][nsj] == 0 and t[nti][ntj] == 0)) continue;
                            if(self(self, nsi, nsj, nti, ntj)) return true;
                        }
                        return false;
                    };
                    if(dfs(dfs, si, sj, ti, tj)) return true;
                }
            }
            rotate(tx.begin(), tx.begin() + 1, tx.end());
            rotate(ty.begin(), ty.begin() + 1, ty.end());
        }
        swap(tx[1], tx[3]);
        swap(ty[1], ty[3]);
    }
    return false;
}

int main() {
    while(true) {
        int w = in(), h = in();
        if(make_pair(w, h) == make_pair(0, 0)) return 0;
        print(solve(w, h) ? "YES" : "NO");
    }
}
accuracy: 1
time_ms: 170
memory_kb: 3364
final_rank: 3

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

#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")

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

struct UnionFind
{
    int n;
    vector<int> par;
    int connected_num;
    
    UnionFind() = default;
    UnionFind(int _n) : n(_n), connected_num(_n), par(_n)
    {
        for (int i = 0; i < n; ++i) par[i] = i;
    }
    
    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)
    {
        if (same(x, y)) return;
        par[root(y)] = root(x);
        connected_num--;
        return;
    }
    
};

bool is_end = false;

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

using bs = bitset<40>;
bs full;

bool debug = false;

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

bool edakari(const bs bit, int nex, const vector<vector<int>> &graph)
{
    UnionFind tree(N);
    int s = -1;
    for (int i = 0; i < N; ++i)
    {
        if (bit[i] && s == -1 && i < nex) s = i;
        for (auto j : graph[i])
        {
            if (bit[i] && bit[j]) tree.merge(i, j);
        }
    }
    if (s == -1) return true;
    
    int r = tree.root(s);
    bool ret = true;
    for (int i = 0; i < nex; ++i)
    {
        if (bit[i]) ret &= (tree.root(i) == r);
    }
    
    return ret;
}

bool dfs(bs bit1, bs bit2, int cnt, int nex, 
    const vector<int> &aite1, const vector<int> &aite2, const vector<vector<int>> &graph)
{
    assert((bit1 & bit2) == 0);
    
    if (cnt * 2 == N)
    {
        bool flg = true;
        flg &= edakari(bit1, N, graph);
        flg &= edakari(bit2, N, graph);
        return flg;
    }
    
    {
        bool flg = true;
        flg &= edakari(bit1 ^ full, nex, graph);
        flg &= edakari(bit2 ^ full, nex, graph);
        if (!flg) return false;
    }
    
    bool ret = false;
    {
        int i = nex;
        bs unite = bit1 | bit2;
        
        if (unite[i])
        {
            return dfs(bit1, bit2, cnt, i + 1, aite1, aite2, graph);
        }
        
        int j2 = aite1[i];
        if (j2 != -1 && !unite[j2] && i != j2)
        {
            bit1[i] = 1, bit2[j2] = 1;
            ret |= dfs(bit1, bit2, cnt + 1, i + 1, aite1, aite2, graph);
            bit1[i] = 0, bit2[j2] = 0;
        }
        if (ret) return true;
        
        int j1 = aite2[i];
        if (j1 != -1 && !unite[j1] && i != j1)
        {
            bit1[j1] = 1, bit2[i] = 1;
            ret |= dfs(bit1, bit2, cnt + 1, i + 1, aite1, aite2, graph);
            bit1[j1] = 0, bit2[i] = 0;
        }
        if (ret) return true;
        
    }
    
    return ret;
}

void solve()
{
    cin >> W >> H;
    if (H == 0 && W == 0)
    {
        is_end = true;
        return;
    }
    
    vector grid(H+2, vector<bool>(W+2, false));
    N = 0;
    int rx = -1, ry = -1;
    for (int i = 1; i <= H; ++i)
    {
        for (int j = 1; j <= W; ++j)
        {
            int c; cin >> c;
            
            grid[i][j] = c;
            N += c;
            if (c == 1 && rx == -1) rx = i, ry = j;
        }
    }
    H += 2, W += 2;
    
    if (N % 2 == 1)
    {
        cout << "NO" << endl;
        return;
    }
    
    full = bs((1LL<<N) - 1);
    
    vector pos_to_num(H, vector<int>(W, -1));
    vector<array<int, 2>> num_to_pos;
    {
        int cnt = 0;
        for (int i = 0; i < H; ++i)
        {
            for (int j = 0; j < W; ++j)
            {
                if (grid[i][j])
                {
                    num_to_pos.push_back({i, j});
                    pos_to_num[i][j] = cnt;
                    cnt++;
                }
            }
        }
        assert(cnt == N);
    }
    
    vector graph(N, vector<int>());
    for (int i = 0; i < N; ++i)
    {
        for (int j = 0; j < N; ++j)
        {
            auto [ix, iy] = num_to_pos[i];
            auto [jx, jy] = num_to_pos[j];
            
            int d = abs(ix - jx) + abs(iy - jy);
            if (d == 1) graph[i].emplace_back(j);
        }
    }
    
    bool res = false;
    array<int, 4> dx2, dy2;
    int sx = rx, sy = ry;
    for (int id = 0; id < N; ++id)
    {
        auto [tx, ty] = num_to_pos[id];
        if (tx == sx && ty == sy) continue;
        dx2 = {1, 0, -1, 0};
        dy2 = {0, 1, 0, -1};
        
        for (int rev = 0; rev < 2; ++rev)
        {
            for (int rotate = 0; rotate < 4; ++rotate)
            {
                vector<int> aite1(N, -1), aite2(N, -1);
                for (int i = 0; i < N; ++i)
                {
                    auto [x, y] = num_to_pos[i];
                    int diffx = x - sx, diffy = y - sy;
                    int nx = tx + diffx * dx2[0] + diffy * dy2[0];
                    int ny = ty + diffx * dx2[1] + diffy * dy2[1];
                    
                    int j = (isvalid(nx, ny) ? pos_to_num[nx][ny] : -1);
                    aite1[i] = j;
                    if (j >= 0) aite2[j] = i;
                }
                
                bool flg = true;
                for (int i = 0; i < N; ++i)
                {
                    if (aite1[i] == -1 && aite2[i] == -1) flg = false;
                    if (aite1[i] == i || aite2[i] == i) flg = false;
                }
                
                if (flg) res |= dfs(bs(0), bs(0), 0, 0, aite1, aite2, graph);
                
                for (int i = 0; i < 3; ++i)
                {
                    swap(dx2[i], dx2[i+1]);
                    swap(dy2[i], dy2[i+1]);
                }
                
            }
            
            for (int i = 0; i < 4; ++i)
            {
                swap(dx2[i], dy2[i]);
            }
            
        }
        
    }
    
    cout << (res ? "YES" : "NO") << endl;
    
    return;
}


int main()
{
    while (!is_end)
    {
        solve();
    }    
    
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3460
final_rank: 2

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

#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")

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

struct UnionFind
{
    int n;
    vector<int> par;
    int connected_num;
    
    UnionFind() = default;
    UnionFind(int _n) : n(_n), connected_num(_n), par(_n)
    {
        for (int i = 0; i < n; ++i) par[i] = i;
    }
    
    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)
    {
        if (same(x, y)) return;
        par[root(y)] = root(x);
        connected_num--;
        return;
    }
    
    
};

bool is_end = false;

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

using bs = bitset<40>;
bs full;

bool debug = false;

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

bool edakari(const bs bit, int nex, const vector<vector<int>> &graph)
{
    UnionFind tree(N);
    int s = -1;
    for (int i = 0; i < N; ++i)
    {
        if (bit[i] && s == -1 && i < nex) s = i;
        for (auto j : graph[i])
        {
            if (bit[i] && bit[j]) tree.merge(i, j);
        }
    }
    
    if (s == -1) return true;
    int r = tree.root(s);
    bool ret = true;
    for (int i = 0; i < nex; ++i)
    {
        if (bit[i]) ret &= (tree.root(i) == r);
    }
    
    return ret;
}

bool dfs(bs bit1, bs bit2, int cnt, int nex, 
    const vector<int> &aite1, const vector<int> &aite2, const vector<vector<int>> &graph)
{
    if (debug) cout << bit1 << " " << bit2 << endl;
    assert((bit1 & bit2) == 0);
    
    if (cnt * 2 == N)
    {
        bool flg = true;
        flg &= edakari(bit1 , N, graph);
        flg &= edakari(bit2 , N, graph);
        return flg;
    }
    
    // if (cnt % 1 == 0)
    // {
    //     bool flg = true;
    //     flg &= edakari(bit1 ^ full, nex, graph);
    //     flg &= edakari(bit2 ^ full, nex, graph);
        
    //     if (!flg) return false;
    // }
    
    bool ret = false;
    
    {
        int i = nex;
        bs unite = bit1 | bit2;
        
        if (unite[i])
        {
            return dfs(bit1, bit2, cnt, i + 1, aite1, aite2, graph);
        }
        
        int j2 = aite1[i];
        if (j2 != -1 && !unite[j2] && i != j2)
        {
            bit1[i] = 1, bit2[j2] = 1;
            ret |= dfs(bit1, bit2, cnt + 1, i + 1, aite1, aite2, graph);
            bit1[i] = 0, bit2[j2] = 0;
        }
        if (ret) return true;
        
        int j1 = aite2[i];
        if (j1 != -1 && !unite[j1] && i != j1)
        {
            bit1[j1] = 1, bit2[i] = 1;
            ret |= dfs(bit1, bit2, cnt + 1, i + 1, aite1, aite2, graph);
            bit1[j1] = 0, bit2[i] = 0;
        }
        if (ret) return true;
        
    }
    
    return ret;
}

void solve()
{
    cin >> W >> H;
    if (H == 0 && W == 0)
    {
        is_end = true;
        return;
    }
    
    vector grid(H+2, vector<bool>(W+2, false));
    N = 0;
    int rx = -1, ry = -1;
    for (int i = 1; i <= H; ++i)
    {
        for (int j = 1; j <= W; ++j)
        {
            int c; cin >> c;
            
            grid[i][j] = c;
            N += c;
            if (c == 1 && rx == -1) rx = i, ry = j;
        }
    }
    H += 2, W += 2;
    
    if (N % 2 == 1)
    {
        cout << "NO" << endl;
        return;
    }
    
    // cout << rx << " " << ry << endl;
    
    full = bs((1LL<<N) - 1);
    
    vector pos_to_num(H, vector<int>(W, -1));
    vector<array<int, 2>> num_to_pos;
    {
        int cnt = 0;
        for (int i = 0; i < H; ++i)
        {
            for (int j = 0; j < W; ++j)
            {
                if (grid[i][j])
                {
                    num_to_pos.push_back({i, j});
                    pos_to_num[i][j] = cnt;
                    cnt++;
                }
            }
        }
        assert(cnt == N);
    }
    // {
    //     int cnt = 0;
    //     queue<array<int, 2>> que;
        
    //     que.push({rx, ry});
    //     num_to_pos.push_back({rx, ry});
    //     pos_to_num[rx][ry] = cnt;
    //     cnt++;
        
    //     while (!que.empty())
    //     {
    //         auto [x, y] = que.front();
    //         que.pop();
            
    //         for (int dir = 0; dir < 4; ++dir)
    //         {
    //             int nx = x + dx[dir], ny = y + dy[dir];
    //             if (grid[nx][ny] && pos_to_num[nx][ny] == -1)
    //             {
    //                 que.push({nx, ny});
    //                 num_to_pos.push_back({nx, ny});
    //                 pos_to_num[nx][ny] = cnt;
    //                 cnt++;
    //             }
    //         }
            
    //     }
    //     assert(cnt == N);
    // }
    
    // for (int i = 0; i < N; ++i)
    // {
    //     auto [x, y] = num_to_pos[i];
    //     cout << i << " " << x << " " << y << endl;
    // }
    
    vector graph(N, vector<int>());
    for (int i = 0; i < N; ++i)
    {
        for (int j = 0; j < N; ++j)
        {
            auto [ix, iy] = num_to_pos[i];
            auto [jx, jy] = num_to_pos[j];
            
            int d = abs(ix - jx) + abs(iy - jy);
            if (d == 1) graph[i].emplace_back(j);
        }
    }
    
    bool res = false;
    array<int, 4> dx2, dy2;
    int sx = rx, sy = ry;
    for (int id = 0; id < N; ++id)
    {
        auto [tx, ty] = num_to_pos[id];
        if (tx == sx && ty == sy) continue;
        dx2 = {1, 0, -1, 0};
        dy2 = {0, 1, 0, -1};
        
        for (int rev = 0; rev < 2; ++rev)
        {
            for (int rotate = 0; rotate < 4; ++rotate)
            {
                vector<int> aite1(N, -1), aite2(N, -1);
                for (int i = 0; i < N; ++i)
                {
                    auto [x, y] = num_to_pos[i];
                    int diffx = x - sx, diffy = y - sy;
                    int nx = tx + diffx * dx2[0] + diffy * dy2[0];
                    int ny = ty + diffx * dx2[1] + diffy * dy2[1];
                    
                    int j = (isvalid(nx, ny) ? pos_to_num[nx][ny] : -1);
                    aite1[i] = j;
                    if (j >= 0) aite2[j] = i;
                }
                
                bool flg = true;
                for (int i = 0; i < N; ++i)
                {
                    if (aite1[i] == -1 && aite2[i] == -1) flg = false;
                    if (aite1[i] == i || aite2[i] == i) flg = false;
                }
                
                res |= dfs(bs(0), bs(0), 0, 0, aite1, aite2, graph);
                
                for (int i = 0; i < 3; ++i)
                {
                    swap(dx2[i], dx2[i+1]);
                    swap(dy2[i], dy2[i+1]);
                }
                
            }
            
            for (int i = 0; i < 4; ++i)
            {
                swap(dx2[i], dy2[i]);
            }
            
        }
        
    }
    
    
    cout << (res ? "YES" : "NO") << endl;
    
    
    return;
}


int main()
{
    while (!is_end)
    {
        solve();
    }    
    
    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 3080
final_rank: 1

code_snippet: #include <cstdio>
#include <cstdlib>
#include <iostream>
#include <map>
#include <set>
#include <vector>
using namespace std;
typedef long long ll;
const int dx[] = {0, 1, 0, -1};
const int dy[] = {-1, 0, 1, 0};
int w, h, tatu_x[20], tatu_y[20], kazu_x[20], kazu_y[20];
int field[12][12], cx[36], cy[36], csize;
map<pair<int, int>, int> idx;
set<ll> visited[20][4][2];
bool backtrack(int cnt, ll kS, int init_dir, int f) {
  if (visited[cnt][init_dir][f].count(kS))
    return false;
  if (csize / 2 == cnt)
    return true;
  for (int i = 0; i < cnt; i++) {
    for (int k = 0; k < 4; k++) {
      int tx = tatu_x[i] + dx[k];
      int ty = tatu_y[i] + dy[k];
      if (tx < 0 || tx >= w || ty < 0 || ty >= h || field[ty][tx] == 0)
        continue;
      int ttx = kazu_x[i] + dx[(k + init_dir + (f ? 2 : 0)) % 4];
      int tty = kazu_y[i] + dy[(k + init_dir) % 4];
      if ((tx == ttx && ty == tty) || ttx < 0 || ttx >= w || tty < 0 || tty >= h || field[tty][ttx] == 0)
        continue;
      field[ty][tx] = 0;
      tatu_x[cnt] = tx, tatu_y[cnt] = ty;
      field[tty][ttx] = 0;
      kazu_x[cnt] = ttx, kazu_y[cnt] = tty;
      if (backtrack(cnt + 1, kS | (1LL << idx[make_pair(ttx, tty)]), init_dir,
                    f))
        return true;
      field[tty][ttx] = 1;
      field[ty][tx] = 1;
    }
  }
  visited[cnt][init_dir][f].insert(kS);
  return false;
}
bool solve() {
  if (csize % 2)
    return false;
  tatu_x[0] = cx[0], tatu_y[0] = cy[0];
  field[cy[0]][cx[0]] = 0;
  for (int j = 1; j < csize; j++) {
    kazu_x[0] = cx[j], kazu_y[0] = cy[j];
    field[cy[j]][cx[j]] = 0;
    for (int k = 0; k < 4; k++) {
      if (backtrack(1, 1LL << j, k, 0) || backtrack(1, 1LL << j, k, 1))
        return true;
    }
    field[cy[j]][cx[j]] = 1;
  }
  field[cy[0]][cx[0]] = 1;
  return false;
}
int main() {
  while (cin >> w >> h, w | h) {
    idx.clear();
    for (int i = 0; i < 20; i++)
      for (int j = 0; j < 4; j++)
        for (int k = 0; k < 2; k++)
          visited[i][j][k].clear();
    csize = 0;
    for (int i = 0; i < h; i++)
      for (int j = 0; j < w; j++) {
        cin >> field[i][j];
        if (field[i][j] == 1) {
          cx[csize] = j, cy[csize] = i;
          idx[make_pair(j, i)] = csize;
          csize++;
        }
      }
    puts(solve() ? "YES" : "NO");
  }
  return 0;
}
accuracy: 1
time_ms: 1050
memory_kb: 11692
final_rank: 18

code_snippet: #include <cstdio>
#include <cstdlib>
#include <iostream>
#include <map>
#include <set>
#include <vector>
using namespace std;
#define REP(i, a, n) for (i = a; i < n; i++)
#define rep(i, n) REP(i, 0, n)
#define all(x) x.begin(), x.end()
#define foreach(it, x)                                                         \
  for (typeof(x.begin()) it = x.begin(); it != x.end(); it++)
typedef long long ll;
const int dx[] = {0, 1, 0, -1};
const int dy[] = {-1, 0, 1, 0};
int w, h, tatu_x[20], tatu_y[20], kazu_x[20], kazu_y[20];
int field[12][12], cx[36], cy[36], csize;
map<pair<int, int>, int> idx;
set<ll> visited[20][4][2];
inline bool inside(int x, int y) { return !(x < 0 || x >= w || y >= h || y < 0); }
bool backtrack(int cnt, ll kS, int init_dir, int f) {
  int i, j, k;
  if (visited[cnt][init_dir][f].count(kS))
    return false;
  if (csize / 2 == cnt)
    return true;
  rep(i, cnt) {
    rep(k, 4) {
      int tx = tatu_x[i] + dx[k];
      int ty = tatu_y[i] + dy[k];
      if (!inside(tx, ty) || field[ty][tx] == 0)
        continue;
      int ttx = kazu_x[i] + dx[(k + init_dir + (f ? 2 : 0)) % 4];
      int tty = kazu_y[i] + dy[(k + init_dir) % 4];
      if ((tx == ttx && ty == tty) || !inside(ttx, tty) || field[tty][ttx] == 0)
        continue;
      field[ty][tx] = 0;
      tatu_x[cnt] = tx, tatu_y[cnt] = ty;
      field[tty][ttx] = 0;
      kazu_x[cnt] = ttx, kazu_y[cnt] = tty;
      if (backtrack(cnt + 1, kS | (1LL << idx[{ttx, tty}]), init_dir,
                    f))
        return true;
      field[tty][ttx] = 1;
      field[ty][tx] = 1;
    }
  }
  visited[cnt][init_dir][f].insert(kS);
  return false;
}
bool solve() {
  int i, j, k;
  if (csize % 2)
    return false;
  tatu_x[0] = cx[0], tatu_y[0] = cy[0];
  field[cy[0]][cx[0]] = 0;
  REP(j, 1, csize) {
    kazu_x[0] = cx[j], kazu_y[0] = cy[j];
    field[cy[j]][cx[j]] = 0;
    rep(k, 4) {
      if (backtrack(1, 1LL << j, k, 0))
        return true;
      if (backtrack(1, 1LL << j, k, 1))
        return true;
    }
    field[cy[j]][cx[j]] = 1;
  }
  field[cy[0]][cx[0]] = 1;
  return false;
}
int main() {
  int i, j, k, u;
  while (cin >> w >> h, w | h) {
    idx.clear();
    rep(i, 20) rep(j, 4) rep(k, 2) visited[i][j][k].clear();
    csize = 0;
    rep(i, h) rep(j, w) {
      cin >> field[i][j];
      if (field[i][j]) {
        cx[csize] = j, cy[csize] = i;
        idx[{j, i}] = csize;
        csize++;
      }
    }
    puts(solve() ? "YES" : "NO");
  }
  return 0;
}
accuracy: 1
time_ms: 1050
memory_kb: 11668
final_rank: 15

code_snippet: #include <cstdio>
#include <cstdlib>
#include <iostream>
#include <map>
#include <set>
#include <tr1/unordered_set>
#include <vector>
using namespace std;
using namespace tr1;
#define REP(i, a, n) for (i = a; i < n; i++)
#define rep(i, n) REP(i, 0, n)
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define foreach(it, x)                                                         \
  for (typeof(x.begin()) it = x.begin(); it != x.end(); it++)
typedef long long ll;
const int dx[] = {0, 1, 0, -1};
const int dy[] = {-1, 0, 1, 0};
int w, h, tatu_x[20], tatu_y[20], kazu_x[20], kazu_y[20];
int field[12][12], cx[36], cy[36], csize;
map<pair<int, int>, int> idx;
unordered_set<ll> visited[20][4][2];
bool inside(int x, int y) { return !(x < 0 || x >= w || y >= h || y < 0); }
bool backtrack(int cnt, ll kS, int init_dir, int f) {
  int i, j, k;
  if (visited[cnt][init_dir][f].count(kS))
    return false;
  if (csize / 2 == cnt)
    return true;
  rep(i, cnt) {
    rep(k, 4) {
      int tx = tatu_x[i] + dx[k];
      int ty = tatu_y[i] + dy[k];
      if (!inside(tx, ty) || field[ty][tx] == 0)
        continue;
      int ttx = kazu_x[i] + dx[(k + init_dir + (f ? 2 : 0)) % 4];
      int tty = kazu_y[i] + dy[(k + init_dir) % 4];
      if ((tx == ttx && ty == tty) || !inside(ttx, tty) || field[tty][ttx] == 0)
        continue;
      field[ty][tx] = 0;
      tatu_x[cnt] = tx, tatu_y[cnt] = ty;
      field[tty][ttx] = 0;
      kazu_x[cnt] = ttx, kazu_y[cnt] = tty;
      if (backtrack(cnt + 1, kS | (1LL << idx[make_pair(ttx, tty)]), init_dir,
                    f))
        return true;
      field[tty][ttx] = 1;
      field[ty][tx] = 1;
    }
  }
  visited[cnt][init_dir][f].insert(kS);
  return false;
}
bool solve() {
  int i, j, k;
  if (csize % 2)
    return false;
  tatu_x[0] = cx[0], tatu_y[0] = cy[0];
  field[cy[0]][cx[0]] = 0;
  REP(j, 1, csize) {
    kazu_x[0] = cx[j], kazu_y[0] = cy[j];
    field[cy[j]][cx[j]] = 0;
    rep(k, 4) {
      if (backtrack(1, 1LL << j, k, 0))
        return true;
      if (backtrack(1, 1LL << j, k, 1))
        return true;
    }
    field[cy[j]][cx[j]] = 1;
  }
  field[cy[0]][cx[0]] = 1;
  return false;
}
int main() {
  int i, j, k, u;
  while (cin >> w >> h, w | h) {
    idx.clear();
    rep(i, 20) rep(j, 4) rep(k, 2) visited[i][j][k].clear();
    csize = 0;
    rep(i, h) rep(j, w) {
      cin >> field[i][j];
      if (field[i][j] == 1) {
        cx[csize] = j, cy[csize] = i;
        idx[make_pair(j, i)] = csize;
        csize++;
      }
    }
    puts(solve() ? "YES" : "NO");
  }
  return 0;
}
accuracy: 1
time_ms: 590
memory_kb: 10936
final_rank: 9

code_snippet: #include <cstdio>
#include <cstdlib>
#include <iostream>
#include <map>
#include <set>
#include <vector>
using namespace std;
#define REP(i, a, n) for (i = a; i < n; i++)
#define rep(i, n) REP(i, 0, n)
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define foreach(it, x)                                                         \
  for (typeof(x.begin()) it = x.begin(); it != x.end(); it++)
typedef long long ll;
const int dx[] = {0, 1, 0, -1};
const int dy[] = {-1, 0, 1, 0};
int w, h, tatu_x[20], tatu_y[20], kazu_x[20], kazu_y[20];
int field[12][12], cx[36], cy[36], csize;
map<pair<int, int>, int> idx;
set<ll> visited[20][4][2];
bool inside(int x, int y) { return !(x < 0 || x >= w || y >= h || y < 0); }
bool backtrack(int cnt, ll kS, int init_dir, int f) {
  int i, j, k;
  if (visited[cnt][init_dir][f].count(kS))
    return false;
  if (csize / 2 == cnt)
    return true;
  rep(i, cnt) {
    rep(k, 4) {
      int tx = tatu_x[i] + dx[k];
      int ty = tatu_y[i] + dy[k];
      if (!inside(tx, ty) || field[ty][tx] == 0)
        continue;
      int ttx = kazu_x[i] + dx[(k + init_dir + (f ? 2 : 0)) % 4];
      int tty = kazu_y[i] + dy[(k + init_dir) % 4];
      if ((tx == ttx && ty == tty) || !inside(ttx, tty) || field[tty][ttx] == 0)
        continue;
      field[ty][tx] = 0;
      tatu_x[cnt] = tx, tatu_y[cnt] = ty;
      field[tty][ttx] = 0;
      kazu_x[cnt] = ttx, kazu_y[cnt] = tty;
      if (backtrack(cnt + 1, kS | (1LL << idx[make_pair(ttx, tty)]), init_dir,
                    f))
        return true;
      field[tty][ttx] = 1;
      field[ty][tx] = 1;
    }
  }
  visited[cnt][init_dir][f].insert(kS);
  return false;
}
bool solve() {
  int i, j, k;
  if (csize % 2)
    return false;
  tatu_x[0] = cx[0], tatu_y[0] = cy[0];
  field[cy[0]][cx[0]] = 0;
  REP(j, 1, csize) {
    kazu_x[0] = cx[j], kazu_y[0] = cy[j];
    field[cy[j]][cx[j]] = 0;
    rep(k, 4) {
      if (backtrack(1, 1LL << j, k, 0))
        return true;
      if (backtrack(1, 1LL << j, k, 1))
        return true;
    }
    field[cy[j]][cx[j]] = 1;
  }
  field[cy[0]][cx[0]] = 1;
  return false;
}
int main() {
  int i, j, k, u;
  while (cin >> w >> h, w | h) {
    idx.clear();
    rep(i, 20) rep(j, 4) rep(k, 2) visited[i][j][k].clear();
    csize = 0;
    rep(i, h) rep(j, w) {
      cin >> field[i][j];
      if (field[i][j] == 1) {
        cx[csize] = j, cy[csize] = i;
        idx[make_pair(j, i)] = csize;
        csize++;
      }
    }
    puts(solve() ? "YES" : "NO");
  }
  return 0;
}
accuracy: 1
time_ms: 1060
memory_kb: 11664
final_rank: 16

code_snippet: #include <cstdio>
#include <cstdlib>
#include <iostream>
#include <map>
#include <set>
#include <vector>
using namespace std;

#define REP(i, a, n) for (int i = a; i < n; i++)
#define rep(i, n) REP(i, 0, n)
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define foreach(it, x) for (typeof(x.begin()) it = x.begin(); it != x.end(); it++)
typedef long long ll;
const int dx[] = {0, 1, 0, -1};
const int dy[] = {-1, 0, 1, 0};
int w, h, tatu_x[20], tatu_y[20], kazu_x[20], kazu_y[20];
int field[12][12], cx[36], cy[36], csize;
map<pair<int, int>, int> idx;
set<ll> visited[20][4][2];

// Check if the point is inside the field
bool inside(int x, int y) {
    return !(x < 0 || x >= w || y >= h || y < 0);
}

// Backtracking function
bool backtrack(int cnt, ll kS, int init_dir, int f) {
    if (visited[cnt][init_dir][f].count(kS)) {
        return false;
    }
    if (csize / 2 == cnt) {
        return true;
    }
    rep(i, cnt) {
        rep(k, 4) {
            int tx = tatu_x[i] + dx[k];
            int ty = tatu_y[i] + dy[k];
            if (!inside(tx, ty) || field[ty][tx] == 0) {
                continue;
            }
            int ttx = kazu_x[i] + dx[(k + init_dir + (f ? 2 : 0)) % 4];
            int tty = kazu_y[i] + dy[(k + init_dir) % 4];
            if ((tx == ttx && ty == tty) || !inside(ttx, tty) || field[tty][ttx] == 0) {
                continue;
            }
            field[ty][tx] = 0;
            tatu_x[cnt] = tx, tatu_y[cnt] = ty;
            field[tty][ttx] = 0;
            kazu_x[cnt] = ttx, kazu_y[cnt] = tty;
            if (backtrack(cnt + 1, kS | (1LL << idx[make_pair(ttx, tty)]), init_dir, f)) {
                return true;
            }
            field[tty][ttx] = 1;
            field[ty][tx] = 1;
        }
    }
    visited[cnt][init_dir][f].insert(kS);
    return false;
}

bool solve() {
    if (csize % 2) {
        return false;
    }
    tatu_x[0] = cx[0], tatu_y[0] = cy[0];
    field[cy[0]][cx[0]] = 0;
    REP(j, 1, csize) {
        kazu_x[0] = cx[j], kazu_y[0] = cy[j];
        field[cy[j]][cx[j]] = 0;
        rep(k, 4) {
            if (backtrack(1, 1LL << j, k, 0)) {
                return true;
            }
            if (backtrack(1, 1LL << j, k, 1)) {
                return true;
            }
        }
        field[cy[j]][cx[j]] = 1;
    }
    field[cy[0]][cx[0]] = 1;
    return false;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    while (cin >> w >> h, w | h) {
        idx.clear();
        rep(i, 20) rep(j, 4) rep(k, 2) visited[i][j][k].clear();
        csize = 0;
        rep(i, h) rep(j, w) {
            cin >> field[i][j];
            if (field[i][j] == 1) {
                cx[csize] = j, cy[csize] = i;
                idx[make_pair(j, i)] = csize;
                csize++;
            }
        }
        puts(solve() ? "YES" : "NO");
    }
    return 0;
}
accuracy: 1
time_ms: 1070
memory_kb: 11704
final_rank: 19

code_snippet: #include <cstdio>
#include <cstdlib>
#include <iostream>
#include <map>
#include <set>
#include <vector>
using namespace std;

#define REP(i, a, n) for (int i = a; i < n; i++)
#define rep(i, n) REP(i, 0, n)
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define foreach(it, x) for (auto it = x.begin(); it != x.end(); it++)
typedef long long ll;

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

int w, h, tatu_x[20], tatu_y[20], kazu_x[20], kazu_y[20];
int field[12][12], cx[36], cy[36], csize;
map<pair<int, int>, int> idx;
set<ll> visited[20][4][2];

inline bool inside(int x, int y) {
  return !(x < 0 || x >= w || y >= h || y < 0);
}

bool backtrack(int cnt, ll kS, int init_dir, int f) {
  if (visited[cnt][init_dir][f].count(kS)) return false;
  if (csize / 2 == cnt) return true;

  rep(i, cnt) {
    rep(k, 4) {
      int tx = tatu_x[i] + dx[k];
      int ty = tatu_y[i] + dy[k];
      if (!inside(tx, ty) || field[ty][tx] == 0) continue;

      int ttx = kazu_x[i] + dx[(k + init_dir + (f ? 2 : 0)) % 4];
      int tty = kazu_y[i] + dy[(k + init_dir) % 4];
      if ((tx == ttx && ty == tty) || !inside(ttx, tty) || field[tty][ttx] == 0)
        continue;

      field[ty][tx] = 0;
      tatu_x[cnt] = tx, tatu_y[cnt] = ty;
      field[tty][ttx] = 0;
      kazu_x[cnt] = ttx, kazu_y[cnt] = tty;

      if (backtrack(cnt + 1, kS | (1LL << idx[make_pair(ttx, tty)]), init_dir,
                    f)) return true;

      field[tty][ttx] = 1;
      field[ty][tx] = 1;
    }
  }

  visited[cnt][init_dir][f].insert(kS);
  return false;
}

bool solve() {
  if (csize % 2) return false;

  tatu_x[0] = cx[0], tatu_y[0] = cy[0];
  field[cy[0]][cx[0]] = 0;

  REP(j, 1, csize) {
    kazu_x[0] = cx[j], kazu_y[0] = cy[j];
    field[cy[j]][cx[j]] = 0;

    rep(k, 4) {
      if (backtrack(1, 1LL << j, k, 0)) return true;
      if (backtrack(1, 1LL << j, k, 1)) return true;
    }

    field[cy[j]][cx[j]] = 1;
  }

  field[cy[0]][cx[0]] = 1;
  return false;
}

int main() {
  while (cin >> w >> h, w | h) {
    idx.clear();
    rep(i, 20) rep(j, 4) rep(k, 2) visited[i][j][k].clear();
    csize = 0;

    rep(i, h) rep(j, w) {
      cin >> field[i][j];
      if (field[i][j] == 1) {
        cx[csize] = j, cy[csize] = i;
        idx[make_pair(j, i)] = csize;
        csize++;
      }
    }

    puts(solve() ? "YES" : "NO");
  }

  return 0;
}
accuracy: 1
time_ms: 1060
memory_kb: 11672
final_rank: 17

code_snippet: #include <cstdio>
#include <cstdlib>
#include <iostream>
#include <map>
#include <set>
#include <vector>
using namespace std;
#define REP(i, a, n) for (int i = (a); i < (n); i++)
#define rep(i, n) REP(i, 0, n)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define foreach(it, x)                                                         \
  for (typeof((x).begin()) it = (x).begin(); it != (x).end(); it++)
typedef long long ll;
const int dx[] = {0, 1, 0, -1};
const int dy[] = {-1, 0, 1, 0};
int w, h, tatu_x[20], tatu_y[20], kazu_x[20], kazu_y[20];
int field[12][12], cx[36], cy[36], csize;
map<pair<int, int>, int> idx;
set<ll> visited[20][4][2];
bool inside(int x, int y) { return !(x < 0 || x >= w || y >= h || y < 0); }
bool backtrack(int cnt, ll kS, int init_dir, int f) {
  if (visited[cnt][init_dir][f].count(kS))
    return false;
  if (csize / 2 == cnt)
    return true;
  for (int i = 0; i < cnt; i++) {
    for (int k = 0; k < 4; k++) {
      int tx = tatu_x[i] + dx[k];
      int ty = tatu_y[i] + dy[k];
      if (!inside(tx, ty) || field[ty][tx] == 0)
        continue;
      int ttx = kazu_x[i] + dx[(k + init_dir + (f ? 2 : 0)) % 4];
      int tty = kazu_y[i] + dy[(k + init_dir) % 4];
      if ((tx == ttx && ty == tty) || !inside(ttx, tty) || field[tty][ttx] == 0)
        continue;
      field[ty][tx] = 0, tatu_x[cnt] = tx, tatu_y[cnt] = ty;
      field[tty][ttx] = 0, kazu_x[cnt] = ttx, kazu_y[cnt] = tty;
      if (backtrack(cnt + 1, kS | (1LL << idx[make_pair(ttx, tty)]), init_dir,
                    f))
        return true;
      field[tty][ttx] = 1, field[ty][tx] = 1;
    }
  }
  visited[cnt][init_dir][f].insert(kS);
  return false;
}
bool solve() {
  if (csize % 2)
    return false;
  tatu_x[0] = cx[0], tatu_y[0] = cy[0];
  field[cy[0]][cx[0]] = 0;
  REP(j, 1, csize) {
    kazu_x[0] = cx[j], kazu_y[0] = cy[j];
    field[cy[j]][cx[j]] = 0;
    rep(k, 4) {
      if (backtrack(1, 1LL << j, k, 0))
        return true;
      if (backtrack(1, 1LL << j, k, 1))
        return true;
    }
    field[cy[j]][cx[j]] = 1;
  }
  field[cy[0]][cx[0]] = 1;
  return false;
}
int main() {
  while (cin >> w >> h, w | h) {
    idx.clear();
    rep(i, 20) rep(j, 4) rep(k, 2) visited[i][j][k].clear();
    csize = 0;
    rep(i, h) rep(j, w) {
      cin >> field[i][j];
      if (field[i][j] == 1) {
        cx[csize] = j, cy[csize] = i;
        idx[make_pair(j, i)] = csize;
        csize++;
      }
    }
    puts(solve() ? "YES" : "NO");
  }
  return 0;
}
accuracy: 1
time_ms: 1060
memory_kb: 11592
final_rank: 11

code_snippet: #include <cstdio>
#include <cstdlib>
#include <iostream>
#include <map>
#include <set>
#include <vector>
using namespace std;

#define REP(i, a, n) for (int i = a; i < n; i++)
#define rep(i, n) REP(i, 0, n)
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define foreach(it, x) for (auto it = x.begin(); it != x.end(); it++)
typedef long long ll;
const int dx[] = {0, 1, 0, -1};
const int dy[] = {-1, 0, 1, 0};
int w, h, tatu_x[20], tatu_y[20], kazu_x[20], kazu_y[20];
int field[12][12], cx[36], cy[36], csize;
map<pair<int, int>, int> idx;
set<ll> visited[20][4][2];

bool inside(int x, int y) { return !(x < 0 || x >= w || y >= h || y < 0); }

bool backtrack(int cnt, ll kS, int init_dir, int f) {
  if (visited[cnt][init_dir][f].count(kS)) return false;
  if (csize / 2 == cnt) return true;
  rep(i, cnt) {
    rep(k, 4) {
      int tx = tatu_x[i] + dx[k];
      int ty = tatu_y[i] + dy[k];
      if (!inside(tx, ty) || field[ty][tx] == 0) continue;
      int ttx = kazu_x[i] + dx[(k + init_dir + (f ? 2 : 0)) % 4];
      int tty = kazu_y[i] + dy[(k + init_dir) % 4];
      if ((tx == ttx && ty == tty) || !inside(ttx, tty) ||
          field[tty][ttx] == 0)
        continue;
      field[ty][tx] = 0;
      tatu_x[cnt] = tx, tatu_y[cnt] = ty;
      field[tty][ttx] = 0;
      kazu_x[cnt] = ttx, kazu_y[cnt] = tty;
      if (backtrack(cnt + 1, kS | (1LL << idx[make_pair(ttx, tty)]), init_dir,
                    f))
        return true;
      field[tty][ttx] = 1;
      field[ty][tx] = 1;
    }
  }
  visited[cnt][init_dir][f].insert(kS);
  return false;
}

bool solve() {
  if (csize % 2) return false;
  tatu_x[0] = cx[0], tatu_y[0] = cy[0];
  field[cy[0]][cx[0]] = 0;
  REP(j, 1, csize) {
    kazu_x[0] = cx[j], kazu_y[0] = cy[j];
    field[cy[j]][cx[j]] = 0;
    rep(k, 4) {
      if (backtrack(1, 1LL << j, k, 0)) return true;
      if (backtrack(1, 1LL << j, k, 1)) return true;
    }
    field[cy[j]][cx[j]] = 1;
  }
  field[cy[0]][cx[0]] = 1;
  return false;
}

int main() {
  while (cin >> w >> h, w | h) {
    idx.clear();
    rep(i, 20) rep(j, 4) rep(k, 2) visited[i][j][k].clear();
    csize = 0;
    rep(i, h) rep(j, w) {
      cin >> field[i][j];
      if (field[i][j] == 1) {
        cx[csize] = j, cy[csize] = i;
        idx[make_pair(j, i)] = csize;
        csize++;
      }
    }
    puts(solve() ? "YES" : "NO");
  }
  return 0;
}
accuracy: 1
time_ms: 1060
memory_kb: 11648
final_rank: 13

code_snippet: #include <cstdio>
#include <cstdlib>
#include <iostream>
#include <map>
#include <set>
#include <vector>
using namespace std;
#define REP(i, a, n) for (int i = a; i < n; i++)
#define rep(i, n) REP(i, 0, n)
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define foreach(it, x)                                                         \
  for (auto it = x.begin(); it != x.end(); it++)
typedef long long ll;
const int dx[] = {0, 1, 0, -1};
const int dy[] = {-1, 0, 1, 0};
int w, h, tatu_x[20], tatu_y[20], kazu_x[20], kazu_y[20];
int field[12][12], cx[36], cy[36], csize;
map<pair<int, int>, int> idx;
set<ll> visited[20][4][2];
bool inside(int x, int y) { return !(x < 0 || x >= w || y >= h || y < 0); }
bool backtrack(int cnt, ll kS, int init_dir, int f) {
  if (visited[cnt][init_dir][f].count(kS))
    return false;
  if (csize / 2 == cnt)
    return true;
  rep(i, cnt) {
    rep(k, 4) {
      int tx = tatu_x[i] + dx[k];
      int ty = tatu_y[i] + dy[k];
      if (!inside(tx, ty) || field[ty][tx] == 0)
        continue;
      int ttx = kazu_x[i] + dx[(k + init_dir + (f ? 2 : 0)) % 4];
      int tty = kazu_y[i] + dy[(k + init_dir) % 4];
      if ((tx == ttx && ty == tty) || !inside(ttx, tty) || field[tty][ttx] == 0)
        continue;
      field[ty][tx] = 0;
      tatu_x[cnt] = tx, tatu_y[cnt] = ty;
      field[tty][ttx] = 0;
      kazu_x[cnt] = ttx, kazu_y[cnt] = tty;
      if (backtrack(cnt + 1, kS | (1LL << idx[make_pair(ttx, tty)]), init_dir,
                    f))
        return true;
      field[tty][ttx] = 1;
      field[ty][tx] = 1;
    }
  }
  visited[cnt][init_dir][f].insert(kS);
  return false;
}
bool solve() {
  if (csize % 2)
    return false;
  tatu_x[0] = cx[0], tatu_y[0] = cy[0];
  field[cy[0]][cx[0]] = 0;
  REP(j, 1, csize) {
    kazu_x[0] = cx[j], kazu_y[0] = cy[j];
    field[cy[j]][cx[j]] = 0;
    rep(k, 4) {
      if (backtrack(1, 1LL << j, k, 0))
        return true;
      if (backtrack(1, 1LL << j, k, 1))
        return true;
    }
    field[cy[j]][cx[j]] = 1;
  }
  field[cy[0]][cx[0]] = 1;
  return false;
}
int main() {
  while (cin >> w >> h, w | h) {
    idx.clear();
    rep(i, 20) rep(j, 4) rep(k, 2) visited[i][j][k].clear();
    csize = 0;
    rep(i, h) rep(j, w) {
      cin >> field[i][j];
      if (field[i][j] == 1) {
        cx[csize] = j, cy[csize] = i;
        idx[make_pair(j, i)] = csize;
        csize++;
      }
    }
    puts(solve() ? "YES" : "NO");
  }
  return 0;
}
accuracy: 1
time_ms: 1060
memory_kb: 11648
final_rank: 13

code_snippet: #include <cstdio>
#include <cstdlib>
#include <iostream>
#include <map>
#include <set>
#include <vector>
using namespace std;
#define REP(i, a, n) for (int i = a; i < n; i++)
#define rep(i, n) REP(i, 0, n)
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define foreach(it, x)                                                         \
  for (auto it = x.begin(); it != x.end(); it++)
typedef long long ll;
const int dx[] = {0, 1, 0, -1};
const int dy[] = {-1, 0, 1, 0};
int w, h, tatu_x[20], tatu_y[20], kazu_x[20], kazu_y[20];
int field[12][12], cx[36], cy[36], csize;
map<pair<int, int>, int> idx;
set<ll> visited[20][4][2];
bool inside(int x, int y) { return !(x < 0 || x >= w || y >= h || y < 0); }
bool backtrack(int cnt, ll kS, int init_dir, int f) {
  if (visited[cnt][init_dir][f].count(kS))
    return false;
  if (csize / 2 == cnt)
    return true;
  for (int i = 0; i < cnt; i++) {
    for (int k = 0; k < 4; k++) {
      int tx = tatu_x[i] + dx[k];
      int ty = tatu_y[i] + dy[k];
      if (!inside(tx, ty) || field[ty][tx] == 0)
        continue;
      int ttx = kazu_x[i] + dx[(k + init_dir + (f ? 2 : 0)) % 4];
      int tty = kazu_y[i] + dy[(k + init_dir) % 4];
      if ((tx == ttx && ty == tty) || !inside(ttx, tty) || field[tty][ttx] == 0)
        continue;
      field[ty][tx] = 0;
      tatu_x[cnt] = tx, tatu_y[cnt] = ty;
      field[tty][ttx] = 0;
      kazu_x[cnt] = ttx, kazu_y[cnt] = tty;
      if (backtrack(cnt + 1, kS | (1LL << idx[make_pair(ttx, tty)]), init_dir,
                    f))
        return true;
      field[tty][ttx] = 1;
      field[ty][tx] = 1;
    }
  }
  visited[cnt][init_dir][f].insert(kS);
  return false;
}
bool solve() {
  if (csize % 2)
    return false;
  tatu_x[0] = cx[0], tatu_y[0] = cy[0];
  field[cy[0]][cx[0]] = 0;
  REP(j, 1, csize) {
    kazu_x[0] = cx[j], kazu_y[0] = cy[j];
    field[cy[j]][cx[j]] = 0;
    rep(k, 4) {
      if (backtrack(1, 1LL << j, k, 0))
        return true;
      if (backtrack(1, 1LL << j, k, 1))
        return true;
    }
    field[cy[j]][cx[j]] = 1;
  }
  field[cy[0]][cx[0]] = 1;
  return false;
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  cout.tie(NULL);
  while (cin >> w >> h, w | h) {
    idx.clear();
    rep(i, 20) rep(j, 4) rep(k, 2) visited[i][j][k].clear();
    csize = 0;
    rep(i, h) rep(j, w) {
      cin >> field[i][j];
      if (field[i][j] == 1) {
        cx[csize] = j, cy[csize] = i;
        idx[make_pair(j, i)] = csize;
        csize++;
      }
    }
    puts(solve() ? "YES" : "NO");
  }
  return 0;
}
accuracy: 1
time_ms: 1060
memory_kb: 11592
final_rank: 11