use std::hash::Hash;
use std::collections::hash_set::Iter;
use std::rc::Rc;
use std::ops::DivAssign;
use std::ops::MulAssign;
use std::ops::SubAssign;
use std::collections::BinaryHeap;
use std::str::FromStr;
use std::collections::HashSet;
use std::collections::BTreeMap;
use std::fmt::Display;
use std::ops::Neg;
use std::ops::Div;
use std::ops::Mul;
use std::ops::Add;
use std::ops::{AddAssign, Sub};
use std::cmp::max;
use std::collections::VecDeque;
use std::cmp::min;
use std::collections::{HashMap, BTreeSet};
use std::cmp::Ordering;
use std::fmt::Debug;

fn read_line() -> String {
    let mut buffer = String::new();
    std::io::stdin().read_line(&mut buffer).expect("No Line");
    buffer.trim().to_owned()
}
fn read_lines<T: std::str::FromStr>(count: usize) -> Vec<T> {
    let mut buffer = String::new();
    let mut vec = Vec::with_capacity(count);
    for _ in 0 .. count {
        std::io::stdin().read_line(&mut buffer).expect("No Line");
        vec.push(buffer.trim().parse().ok().expect("Can't Parse"));
        buffer.clear();
    }
    vec
}
fn read_tabulate<R, T: Fn(&str)->R> (count: usize, transformer: T) -> Vec<R> {
    let mut buffer = String::new();
    let mut vec = Vec::with_capacity(count);
    for _ in 0 .. count {
        std::io::stdin().read_line(&mut buffer).expect("No Line");
        vec.push(transformer(buffer.trim()));
        buffer.clear();
    }
    vec
}
fn read_value<T: std::str::FromStr>() -> T {
    read_line().trim().parse().ok().unwrap()
}
fn read_values<T: std::str::FromStr>() -> Vec<T> {
    read_line().trim().split_whitespace().map(|x| x.parse().ok().expect("Can't Parse")).collect::<Vec<T>>()
}
macro_rules! freeze {
    ($($id:ident), *) => {
        $(let $id = $id;)*
    };
}
macro_rules! read_map {
    ($ident: ident: [$block: block; $size: expr]) => {
        let $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
    (mut $ident: ident: [$block: block; $size: expr]) => {
        let mut $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
}
macro_rules! read {
    (mut $ident: ident: String) => {
        let mut $ident = read_value::<String>();
    };
    ($ident: ident: String) => {
        let $ident = read_value::<String>();
    };
    (mut $ident: ident: [$ty:ty]) => {
        let mut $ident = read_values::<$ty>();
    };
    ($ident: ident: [$ty:ty]) => {
        let $ident = read_values::<$ty>();
    };
    (mut $ident: ident: [[$ty:ty]; $size: expr]) => {
        let mut $ident = (0 .. $size).into_iter().map(|_| read_values::<$ty>()).collect::<Vec<_>>();
    };
    ($ident: ident: [[$ty:ty]; $size: expr]) => {
        let $ident = (0 .. $size).into_iter().map(|_| read_values::<$ty>()).collect::<Vec<_>>();
    };
    (mut $ident: ident: [$ty:ty; $size:expr]) => {
        let mut $ident = read_lines::<$ty>($size);
    };
    ($ident: ident: [$ty:ty; $size:expr]) => {
        let $ident = read_lines::<$ty>($size);
    };
    ($ident: ident: [$block: block; $size: expr]) => {
        let $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
    (mut $ident: ident: [$block: block; $size: expr]) => {
        let mut $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
    ($($token: tt)*) => {
        let mut iter = read_values::<String>().into_iter();
        read_from_iter!(iter; $($token)*);
    };
}
macro_rules! read_from_iter {
    ($iter:expr; mut $ident:ident:$ty:ty, $($rest:tt)*) => {
        let mut $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
        read_from_iter!($iter; $($rest)*);
    };
    ($iter:expr; $ident:ident:$ty:ty, $($rest:tt)*) => {
        let $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
        read_from_iter!($iter; $($rest)*);
    };
    ($iter:expr; mut $ident:ident:$ty:ty) => {
        let mut $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
    };
    ($iter:expr; $ident:ident:$ty:ty) => {
        let $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
    };
    ($iter: expr; ) => {};
}
struct KeyValue<K, V> {
    key: K,
    value: V
}
impl <K: PartialOrd, V> PartialEq for KeyValue<K, V> {
    fn eq(&self, other: &Self) -> bool {
        self.key.eq(&other.key)
    }
}
impl <K: PartialOrd, V> Eq for KeyValue<K, V> {}
impl <K: PartialOrd, V> PartialOrd for KeyValue<K, V> {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        self.key.partial_cmp(&other.key)
    }
}
impl <K: PartialOrd, V> Ord for KeyValue<K, V> {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.key.partial_cmp(&other.key).ok_or("Can't Compare").unwrap()
    }
}
#[derive(Eq, PartialEq)]
struct Rev<T: Ord>(T);
impl <T: std::cmp::Ord> PartialOrd for Rev<T> {
    fn partial_cmp(&self, rhs: &Rev<T>) -> std::option::Option<std::cmp::Ordering> { 
        rhs.0.partial_cmp(&self.0)
    }
}
impl <T: Ord> Ord for Rev<T> {
    fn cmp(&self, rhs: &Self) -> std::cmp::Ordering { 
        rhs.0.cmp(&self.0)
    }
}
#[derive(Copy, Clone, Debug)]
enum Dir {
    Up, Right, Down, Left
}
impl Dir {
    fn all() -> Vec<Dir> {
        vec![Dir::Up, Dir::Right, Dir::Down, Dir::Left]
    }
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
struct Coordinate {
    x: i32, y: i32
}
impl Coordinate {
    fn rotate(&self, dir: Dir, mirror: bool) -> Coordinate {
        if mirror {
            Coordinate{x: -self.x, y: self.y}.rotate(dir, false)
        }else {
            match dir {
                Dir::Up => *self,
                Dir::Right => Coordinate{x: self.y, y: -self.x},
                Dir::Down => Coordinate{x: -self.x, y: - self.y},
                Dir::Left => Coordinate{x: -self.y, y: self.x}
            }
        }
    }
    fn neighbor(&self) -> Vec<Coordinate> {
        vec![Coordinate{x: self.x + 1, y: self.y}, Coordinate{x: self.x - 1, y: self.y}, Coordinate{x: self.x, y: self.y + 1}, Coordinate{x: self.x, y: self.y - 1}]
    }
}
impl Sub for Coordinate {
    type Output = Coordinate;
    fn sub(self, rhs: Coordinate) -> <Self as std::ops::Sub<Coordinate>>::Output {
        Coordinate{x: self.x - rhs.x, y: self.y - rhs.y}
    }
}
impl Add for Coordinate {
    type Output = Coordinate;
    fn add(self, rhs: Coordinate) -> <Self as std::ops::Add<Coordinate>>::Output {
        Coordinate{x: self.x + rhs.x, y: self.y + rhs.y}
    }
}
fn connect_count(a: Coordinate, state: &Vec<Vec<i32>>) -> usize {
    let mut stack = vec![a];
    let mut searched = vec![vec![false; state[0].len()]; state.len()];
    searched[a.y as usize][a.x as usize] = true;
    let mut count = 1;
    let color = state[a.y as usize][a.x as usize];
    while let Some(current) = stack.pop() {
        for next in current.neighbor() {
            if 0 <= next.y && next.y < state.len() as i32 && 0 <= next.x && next.x < state[next.y as usize].len() as i32 && state[next.y as usize][next.x as usize] == color && !searched[next.y as usize][next.x as usize] {
                searched[next.y as usize][next.x as usize] = true;
                stack.push(next);
                count += 1;
            }
        }
    }
    count
}
fn can_separate(a: Coordinate, b: Coordinate, dir: Dir, state: &Vec<Vec<usize>>, mirror: bool) -> bool {
    let mut a_to_b = vec![vec![None; state[0].len()]; state.len()];
    let mut b_to_a = vec![vec![None; state[0].len()]; state.len()];
    let mut coordinates = vec![];
    for i in 0 .. state.len() {
        for j in 0 .. state[i].len() {
            if state[i][j] == 0 {continue;}
            let pos = Coordinate{x: j as i32, y: i as i32};
            coordinates.push(pos);
            let a_diff = pos - a;
            let pair_pos = b + a_diff.rotate(dir, mirror);
            if 0 <= pair_pos.y && pair_pos.y < state.len() as i32 && 0 <= pair_pos.x && pair_pos.x < state[pair_pos.y as usize].len() as i32 && state[pair_pos.y as usize][pair_pos.x as usize] != 0 {
                a_to_b[i][j] = Some(pair_pos);
                b_to_a[pair_pos.y as usize][pair_pos.x as usize] = Some(pos);
            }
        }
    }
    //println!("dir: {:?}, mirror: {}\nA to B: {:?}\nB to A: {:?}", dir, mirror, a_to_b, b_to_a);
    for i in 0 .. state.len() {
        for j in 0 .. state[i].len() {
            if state[i][j] != 0 && a_to_b[i][j].is_none() && b_to_a[i][j].is_none() {
                return false;
            }
        }
    }
    if coordinates.len() & 1 != 0 {return false;}
    for mut pattern in 0 .. (1 << (coordinates.len() >> 1)) {
        let mut separate = vec![vec![0; state[0].len()]; state.len()];
        let mut can = true;
        for i in 0 .. coordinates.len() {
            if separate[coordinates[i].y as usize][coordinates[i].x as usize] == 0 {
                let y = coordinates[i].y as usize;
                let x = coordinates[i].x as usize;
                if pattern & 1 == 0 {
                    if let Some(op) = a_to_b[y][x] {
                        separate[y][x] = 1;
                        separate[op.y as usize][op.x as usize] = 2;
                    }else {
                        can = false;
                        break;
                    }
                }else {
                    if let Some(op) = b_to_a[y][x] {
                        separate[y][x] = 2;
                        separate[op.y as usize][op.x as usize] = 1;
                    }else {
                        can = false;
                        break;
                    }
                }
                pattern >>= 1;
            }
        }
        if !can {continue;}
        for c in &coordinates {
            if let Some(op) = a_to_b[c.y as usize][c.x as usize] {
                if separate[c.y as usize][c.x as usize] == separate[op.y as usize][op.x as usize] {
                    can = false;
                    break;
                }
            }
        }
        if !can {continue;}
        if connect_count(coordinates[0], &separate) << 1 == coordinates.len() {
            return true;
        }
    }
    false
}

fn main() {
    loop {
        read!(width: usize, height: usize);
        if width == 0 && height == 0 {break;}
        read!(state:[[usize]; height]);
        let mut can = false;
        let base = (0 .. height).flat_map(|y| (0 .. width).find(|&x| state[y][x] == 1).map(|x| Coordinate{x: x as i32, y: y as i32})).next().unwrap();
        for i in 0 .. height {
            for j in 0 .. width {
                //println!("i: {}, j: {}", i, j);
                if state[i][j] != 0 && (base.y != i as i32 || base.x != j as i32) {
                    if Dir::all().into_iter().any(|d| can_separate(base, Coordinate{x: j as i32, y: i as i32}, d, &state, true) || can_separate(base, Coordinate{x: j as i32, y: i as i32}, d, &state, false)) {
                        can = true;
                        break;
                    }
                }
            }
        }
        if can {
            println!("YES");
        }else {
            println!("NO");
        }
    }
}


Measured memory_bytes: 5044