//  [rust]
use std::*;
use std::io::*;
use std::iter::Iterator;
use std::str::FromStr;
#[allow(unused_imports)]
use std::fmt::{Display, Formatter};

#[allow(dead_code)]
fn main() {
  let stdin = stdin();
  let r = &mut BufReader::new(stdin.lock());
  let stdout = stdout();
  let w = &mut BufWriter::new(stdout.lock());
  let stderr = stderr();
  let err = &mut BufWriter::new(stderr.lock());
  run(r, w, err);
  w.flush().unwrap();
  err.flush().unwrap();
}

macro_rules! _ft { () => (impl FnOnce(&mut Cursor<Vec<u8>>, &mut Vec<u8>, &mut Vec<u8>)); }

#[allow(dead_code)]
fn test(input: &str, output: &str, f: _ft!()) {
  let r = &mut Cursor::new(input.as_bytes().to_vec());
  let w: &mut Vec<u8> = &mut Vec::new();
  let err: &mut Vec<u8> = &mut Vec::new();
  f(r, w, err);
  let mut stderr = stderr();
  writeln!(stderr, "{}", String::from_utf8(err.to_vec()).unwrap()).unwrap();
  stderr.flush().ok();
  assert_eq!(String::from_utf8(w.to_vec()).unwrap().trim(), output.trim())
}

#[allow(unused_macros)]
macro_rules! t {
  ($f: ident => $input: expr, $output: expr) => (
    #[test]
    fn $f() { test($input, $output, run); }
  );
}

macro_rules! _display_st {
    ($f: expr; $name: expr, ) => (write!($f, "{}", $name)?);
    ($f: expr; $name: expr) => (_display_st!($f; $name, ));
    ($f: expr; $name: expr, $($rest: expr),+, ) => (
      _display_st!($f; $name);
      write!($f, " ")?;
      _display_st!($f; $($rest, )+);
    );
    ($f: expr; $name: expr, $($rest: expr),+) => (_display_st!($f; $name, $($rest, )+));
}

macro_rules! _st_iter_parse {
  ($iter: expr; $($p: ident : $t: ty),+; ) => (Self {
    $($p: $iter.next().unwrap().parse::<$t>().unwrap(), )+
  });
  ($iter: expr; $($p: ident : $t: ty),+; 1~) => (Self {
    $($p: $iter.next().unwrap().parse::<$t>().unwrap() - 1, )+
  });
}

/// 構造体を作成する
#[allow(unused_macros)]
macro_rules! st {
  ($name: ident => $($p: ident : $t: ty),+; $($rest: tt)*) => (
    struct $name { $($p : $t),+ }
    impl FromStr for $name {
      type Err = ();
      fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
        let mut iter = s.split_whitespace();
        Ok(_st_iter_parse!(iter; $($p : $t),+; $($rest)*))
      }
    }
    impl Display for $name {
      fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        _display_st!(f; $(&self.$p, )+);
        Ok(())
      }
    }
  );
  ($name: ident => $($p: ident : $t: ty),+) => (st!($name => $($p : $t),+; ););

  ($name: ident => $($($p: ident),+: $t: ty);+) => (st!($name => $($($p : $t),+),+););
  ($name: ident => $($($p: ident),+: $($t: ty),+);+) => (st!($name => $($($p : $t),+),+););
  ($name: ident => $($p: ident),+: $t: ty) => (st!($name => $($p : $t),+););
  ($name: ident => $($p: ident),+: $($t: ty),+) => (st!($name => $($p : $t),+););

  ($name: ident => $($($p: ident),+: $t: ty);+; $($rest: tt)*) => (
    st!($name => $($($p : $t),+),+; $($rest)*);
  );
  ($name: ident => $($($p: ident),+: $($t: ty),+);+; $($rest: tt)*) => (
    st!($name => $($($p : $t),+),+; $($rest)*);
  );
  ($name: ident => $($p: ident),+: $t: ty; $($rest: tt)*) => (
    st!($name => $($p : $t),+; $($rest)*);
  );
  ($name: ident => $($p: ident),+: $($t: ty),+; $($rest: tt)*) => (
    st!($name => $($p : $t),+; $($rest)*);
  );
}

fn _read_iter<R: Read>(reader: &mut R) -> impl Iterator<Item=char> + '_ {
  reader.by_ref()
    .bytes()
    .map(|c| c.unwrap() as char)
    .skip_while(|c| c.is_whitespace())
}

#[allow(dead_code)]
fn read<F: FromStr, R: Read>(reader: &mut R) -> F {
  let str = _read_iter(reader).take_while(|c| !c.is_whitespace()).collect::<String>();
  str.parse::<F>().ok().unwrap()
}

#[allow(dead_code)]
fn read_line<F: FromStr, R: Read>(reader: &mut R) -> F {
  let str = _read_iter(reader).take_while(|c| c != &'\n').collect::<String>();
  let str = if str.ends_with('\r') { &str[0..str.len() - 1] } else { &str };
  str.parse::<F>().ok().unwrap()
}

#[allow(dead_code)]
fn read1<R: Read, T>(reader: &mut R, mut f: impl FnMut(char) -> T) -> T {
  f(_read_iter(reader).next().unwrap())
}

#[allow(dead_code)]
fn read1_line<R: Read, T>(reader: &mut R, f: impl FnMut(char) -> T) -> Vec<T> {
  _read_iter(reader).take_while(|c| c != &'\n').map(f).collect::<Vec<_>>()
}

/// 1要素読む
#[allow(unused_macros)]
macro_rules! r {
  ($stream: expr) => (read::<String, _>($stream));
  ($stream: expr, ) => (r!($stream));
  ($stream: expr; ) => (r!($stream));

  ($stream: expr; $t: ty) => (read::<$t, _>($stream));
  ($stream: expr; $t: ty; 1~) => (r!($stream; $t) - 1);

  ($stream: expr; $($t: ty),+) => (($(r!($stream; $t)),*));
  ($stream: expr; $($t: ty),+; 1~) => (($(r!($stream; $t) - 1),*));

  ($stream: expr; $t: ty; $n: expr) => (
    (0..$n).map(|_| r!($stream; $t)).collect::<Vec<_>>()
  );
  ($stream: expr; $t: ty; $n: expr; 1~) => (
    (0..$n).map(|_| r!($stream; $t) - 1).collect::<Vec<_>>()
  );

  ($stream: expr; $t: ty; $h: expr, $w: expr) => (
    (0..$h).map(|_| (0..$w).map(|_| r!($stream; $t)).collect::<Vec<_>>()).collect::<Vec<_>>()
  );
  ($stream: expr; $t: ty; $h: expr, $w: expr; 1~) => (
    (0..$h).map(|_| (0..$w).map(|_| r!($stream; $t) - 1).collect::<Vec<_>>()).collect::<Vec<_>>()
  );
}

/// 1文字読む
#[allow(unused_macros)]
macro_rules! r1 {
  ($stream: expr) => (read1($stream, |c| c));
  ($stream: expr, ) => (r!($stream));
  ($stream: expr; ) => (r!($stream));
  ($stream: expr; $f: expr) => (read1($stream, $f));
  ($stream: expr; $f: expr; ) => (r1!($stream, $f));
  ($stream: expr; $f: expr; $n: expr) => ((0..$n).map(|_| r1!($stream; $f)).collect::<Vec<_>>());
  ($stream: expr; $f: expr; $h: expr, $w: expr) => (
    (0..$h).map(|_| (0..$w).map(|_| r1!($stream; $f)).collect::<Vec<_>>()).collect::<Vec<_>>()
  );

  ($stream: expr; @$c: tt; $($tt: tt)*) => (
   r1!($stream; |c| c == stringify!($c).chars().next().unwrap(); $($tt)*)
  );
  ($stream: expr; @$c: tt/$_c: tt; $($tt: tt)*) => (r1!($stream; @$c; $($tt)*));
}

/// 1行読む
#[allow(unused_macros)]
macro_rules! rl {
  ($stream: expr) => (read_line::<String, _>($stream));
  ($stream: expr, ) => (r!($stream));
  ($stream: expr; ) => (r!($stream));
  ($stream: expr; $t: ty) => (read_line::<$t,  _>($stream));
  ($stream: expr; $t: ty; $n: expr) => ((0..$n).map(|_| rl!($stream; $t)).collect::<Vec<_>>());
}

macro_rules! _writes {
  ($stream: expr; $arg0: expr, $($arg: expr),*) => ({
    write!($stream, "{}", $arg0).ok();
    $(write!($stream, " {}", $arg).ok();)*
  });
}

/// 変数を出力
#[allow(unused_macros)]
macro_rules! w {
  ($stream: expr) => (write!($stream, " ").ok());
  ($stream: expr; ) => (w!($stream));
  ($stream: expr, ) => (w!($stream));

  ($stream: expr; $arg: expr) => (write!($stream, "{}", $arg).ok());
  ($stream: expr; $arg: expr, ) => (w!($stream; $arg));

  ($stream: expr; $arg0: expr, $($arg: expr),+) => (_writes!($stream; $arg0, $($arg),+));
  ($stream: expr; $arg0: expr, $($arg: expr),+, ) => (w!($stream; $arg0, $($arg),*));

  ($stream: expr, $($arg: tt)*) => (write!($stream, $($arg)*).ok());
}

/// 変数を改行付きで出力
#[allow(unused_macros)]
macro_rules! wl {
  ($stream: expr) => (writeln!($stream).ok());
  ($stream: expr, ) => (wl!($stream));
  ($stream: expr; ) => (wl!($stream));

  ($stream: expr; $arg: expr) => (writeln!($stream, "{}", $arg).ok());
  ($stream: expr; $arg: expr, ) => (wl!($stream; $arg));

  ($stream: expr; $arg0: expr, $($arg: expr),+) => ({
    _writes!($stream; $arg0, $($arg),+);
    wl!($stream)
  });
  ($stream: expr; $arg0: expr, $($arg: expr),+, ) => (wl!($stream; $arg0, $($arg),*));

  ($stream: expr, $($arg: tt)*) => (writeln!($stream, $($arg)*).ok());
}

/// ベクタを出力
#[allow(unused_macros)]
macro_rules! w_vec {
  ($stream: expr; $vec: expr) => (w_vec!($stream; $vec; $vec.len()));
  ($stream: expr; $vec: expr; $($tt: tt)*) => (w_vec!($stream; $vec => |e| e, " "; $($tt)*));

  ($stream: expr; $vec: expr => $f: expr) => (w_vec!($stream; $vec => $f; $vec.len()));
  ($stream: expr; $vec: expr => $f: expr; $($tt: tt)*) => (
    w_vec!($stream; $vec => $f, ""; $($tt)*)
  );

  ($stream: expr; $vec: expr => $f: expr, $del: expr; $n: expr) => (
    w!($stream; $f($vec[0]));
    for i in 1..$n { w!($stream, "{}{}", $del, $f($vec[i as usize])); }
    wl!($stream);
  );
  ($stream: expr; $vec: expr => $f: expr, $del: expr; $h: expr, $w: expr) => (
    for i in 0..$h { w_vec!($stream; $vec[i as usize] => $f, $del; $w); }
  );

  ($stream: expr; $vec: expr => String) => (w_vec!($stream; $vec => |c| c as char; $vec.len()));
  ($stream: expr; $vec: expr => String; $($tt: tt)*) => (
    w_vec!($stream; $vec => |c| c as char; $($tt)*)
  );

  ($stream: expr; $vec: expr => @$c_t: tt/$c_f: tt) => (
    w_vec!($stream; $vec => @$c_t/$c_f; $vec.len())
  );
  ($stream: expr; $vec: expr => @$c_t: tt/$c_f: tt; $($tt: tt)*) => (
    w_vec!($stream; $vec => |e| if e {stringify!($c_t)} else {stringify!($c_f)}; $($tt)*)
  );
}

#[allow(unused_macros)]
macro_rules! wl_vec {
  ($stream: expr; $vec: expr) => (w_vec!($stream; $vec => |e| e, "\n"; $vec.len()));
  ($stream: expr; $vec: expr; $($tt: tt)*) => (w_vec!($stream; $vec => |e| e, "\n"; $($tt)*));
  ($stream: expr; $vec: expr => $f: expr) => (w_vec!($stream; $vec => $f, "\n"; $vec.len()));
  ($stream: expr; $vec: expr => $f: expr; $($tt: tt)*) => (
    w_vec!($stream; $vec => $f, "\n"; $($tt)*)
  );

  ($stream: expr; $vec: expr => 1~) => (wl_vec!($stream; $vec => |e| e + 1; $vec.len()));
  ($stream: expr; $vec: expr => 1~; $($tt: tt)*) => (
    w_vec!($stream; $vec => |e| e + 1, "\n"; $($tt)*)
  );

  ($stream: expr; $vec: expr => String) => (
    wl_vec!($stream; $vec => |c| c as char, "\n"; $vec.len())
  );
  ($stream: expr; $vec: expr => String; $($tt: tt)*) => (
    w_vec!($stream; $vec => |c| c as char, "\n"; $($tt)*)
  );

  ($stream: expr; $vec: expr => @$c_t: tt/$c_f: tt) => (
    wl_vec!($stream; $vec => @$c_t/$c_f; $vec.len())
  );
  ($stream: expr; $vec: expr => @$c_t: tt/$c_f: tt; $($tt: tt)*) => (
    w_vec!($stream; $vec => |e| if e {stringify!($c_t)} else {stringify!($c_f)}, "\n"; $($tt)*)
  );
}

/// 早期リターン
#[allow(unused_macros)]
macro_rules! early { ($($t: tt)*) => ({ w!($($t)*); return; }); }

/// 配列の初期化
#[allow(unused_macros)]
macro_rules! v {
  ($elem: expr; $n: expr) => (vec![$elem; $n as usize]);
  ($elem: expr; $h: expr, $w: expr) => (vec![vec![$elem; $w as usize]; $h as usize]);
}

// start: Copied Libraries

use std::collections::HashMap;
use std::collections::hash_map::Entry;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::borrow::Borrow;

type Dict<K, V> = HashMap<K, V>;

trait DictAlias<K, V> {
  fn get_(&mut self, key: K) -> &mut V;
  fn get_or_default<'a>(&'a mut self, key: K, default: &'a V) -> &'a V;
  fn set(&mut self, key: K, f: impl FnOnce(&V) -> V) -> Entry<K, V>;
  fn set_value(&mut self, key: K, value: V) -> Entry<K, V>;
  fn set_or_default(&mut self, key: K, f: impl FnOnce(&V) -> V, default: V) -> &mut V;
  fn set_value_or_default(&mut self, key: K, value: V, default: V) -> &mut V;
}

impl<K: std::hash::Hash + Eq, V> DictAlias<K, V> for Dict<K, V> {

  fn get_(&mut self, key: K) -> &mut V { self.get_mut(&key).unwrap() }

  fn get_or_default<'a>(&'a mut self, key: K, default: &'a V) -> &'a V { self.get(&key).unwrap_or(default) }

  fn set(&mut self, key: K, f: impl FnOnce(&V) -> V) -> Entry<K, V> {
    match self.entry(key) {
      Occupied(mut e) => {
        let e_mut = e.get_mut();
        *e_mut = f(e_mut.borrow());
        Occupied(e)
      }
      Vacant(e) => { Vacant(e) }
    }
  }

  fn set_value(&mut self, key: K, value: V) -> Entry<K, V> { self.set(key, |_| value) }

  fn set_or_default(&mut self, key: K, f: impl FnOnce(&V) -> V, default: V) -> &mut V {
    self.set(key, f).or_insert(default)
  }

  fn set_value_or_default(&mut self, key: K, value: V, default: V) -> &mut V {
    self.set_value(key, value).or_insert(default)
  }
}

#[allow(unused_macros)]
macro_rules! dict {
  ($k: ty, $v: ty) => (Dict::<$k, $v>::new());
  ($k: ty, $v: ty; $keys: expr => $value: expr) => ({
    let mut dict = dict!($k, $v);
    for key in $keys { dict.insert(key, $value); }
    dict
  });
}

#[allow(unused_macros)]
macro_rules! dict_vec {
  ($k: ty, $v: ty; $keys: expr) => (dict!($k, Vec<$v>; $keys => Vec::<$v>::new()));
}



trait VecAlias<T> {
  fn get_(&mut self, key: usize) -> &T;
  fn select<U>(&self, f: impl FnMut(&T) -> U) -> Vec<U>;
}

impl<T> VecAlias<T> for Vec<T> {
  fn get_(&mut self, key: usize) -> &T {
    self.get_mut(key).unwrap()
  }
  fn select<U>(&self, mut f: impl FnMut(&T) -> U) -> Vec<U> {
    self.iter().map(|i| f(i)).collect::<Vec<_>>()
  }
}

trait VecOrdAlias<T> {
  fn asc(&mut self);
  fn desc(&mut self);
}

impl<T: Ord> VecOrdAlias<T> for Vec<T> {
  fn asc(&mut self) { self.sort_unstable(); }
  fn desc(&mut self) { self.sort_unstable_by(|i, j| j.cmp(i)); }
}

// end: Copied Libraries


use itertools::max;
// use std::cmp::min;
use std::collections::BinaryHeap;

st!(AB => a, b: usize; 1~);

#[allow(unused_variables)]
fn run<R: Read, W: Write, E: Write>(r_: &mut R, w_: &mut W, err: &mut E) {
  let (n, m) = r!(r_; usize, usize);
  let edges = rl!(r_; AB; m);

  let mut adjs = dict_vec!(usize, usize; 0..n);
  for e in edges.iter() { adjs.get_(e.a).push(e.b); }
  for e in edges.iter() { adjs.get_(e.b).push(e.a); }
  for adj in adjs.iter() { wl!(err; adj.0, adj.1.len()); }

  // let mut deps= v!(usize::MAX; n);
  let mut queue = BinaryHeap::new();
  let mut prevs = v!(usize::MAX; n);
  queue.push(0);
  prevs[0] = 0;

  while !queue.is_empty() {
    let v = queue.pop().unwrap();
    let adjs_v = adjs.get_(v);
    wl!(err, "v: {}", v);
    for &adj in adjs_v.iter() {
      wl!(err, "adj: {}", adj);
      let &prevs_adj = prevs.get_(adj);
      if prevs_adj == usize::MAX {
        queue.push(adj);
        prevs[adj] = v;
        wl!(err, "prevs[{}] = {}", adj, v);
      }
    }
  }
  if *max(prevs.iter()).unwrap() == usize::MAX { early!(w_; "No"); }
  wl!(w_; "Yes");
  let ans = &prevs[1..];
  wl_vec!(w_; ans => 1~);
}

t!(td1 => r"4 4
1 2
2 3
3 4
4 2", r"Yes
1
2
2");
t!(td2 => r"6 9
3 4
6 1
2 4
5 3
4 6
1 5
6 2
4 5
5 6", r"Yes
6
5
5
1
1");