#include <bits/stdc++.h>
#include <boost/multiprecision/cpp_int.hpp>
using namespace std;
using bint = boost::multiprecision::cpp_int;
using ll = long long;
using pint = pair<int, int>;
using pll = pair<ll, ll>;
#define rep(i,n) for (int i = 0; i < (n); i++)
#define repSE(i,s,n) for (int i = (s); i < (n); i++)
#define rrepSE(i,s,e) for (int i = (s); i > (e); i--)
#define ssort(v) sort(v.begin(), v.end())
#define gsort(v) sort(v.rbegin(), v.rend())
template<typename T> istream &operator>>(istream &is, vector<T> &vec){ for (auto &v : vec) is >> v; return is; }
template<typename T> ostream &operator<<(ostream &os, const vector<T> &vec){ os << "["; for (auto v : vec) os << v << ","; os << "]"; return os; }
template<typename T> ostream &operator<<(ostream &os, const deque<T> &vec){ os << "deq["; for (auto v : vec) os << v << ","; os << "]"; return os; }
template<typename T> ostream &operator<<(ostream &os, const set<T> &vec){ os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; }
template<typename T> ostream &operator<<(ostream &os, const unordered_set<T> &vec){ os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; }
template<typename T> ostream &operator<<(ostream &os, const multiset<T> &vec){ os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; }
template<typename T> ostream &operator<<(ostream &os, const unordered_multiset<T> &vec){ os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; }
template<typename T1, typename T2> ostream &operator<<(ostream &os, const pair<T1, T2> &pa){ os << "(" << pa.first << "," << pa.second << ")"; return os; }
template<typename TK, typename TV> ostream &operator<<(ostream &os, const map<TK, TV> &mp){ os << "{"; for (auto v : mp) os << v.first << "=>" << v.second << ","; os << "}"; return os; }
template<typename TK, typename TV> ostream &operator<<(ostream &os, const unordered_map<TK, TV> &mp){ os << "{"; for (auto v : mp) os << v.first << "=>" << v.second << ","; os << "}"; return os; }
template<typename T> bool chmax(T &m, const T q) { if (m < q) {m = q; return true;} else return false; }
template<typename T> bool chmin(T &m, const T q) { if (q < m) {m = q; return true;} else return false; }
#define DEBUG_PRINT(var) std::cout << #var << " = " << var << "\n";

struct UnionFind {
    vector<int> d;
    UnionFind(int n=0): d(n,-1) {}
    int find(int x) {
        if (d[x] < 0) return x;
        return d[x] = find(d[x]);
    }
    bool unite(int x, int y) {
        x = find(x); y = find(y);
        if (x == y) return false;
        if (d[x] > d[y]) swap(x,y);
        d[x] += d[y];
        d[y] = x;
        return true;
    }
    bool same(int x, int y) {return find(x) == find(y);}
    int size(int x) {return -d[find(x)];}
};

vector<int> to[100005];
vector<int> dist, par;
int n, m;

void bfs(int u) {
    queue<pint> S;
    vector<bool> seen;
    seen.assign(n, false);
    // bfs
    S.push(pint(u, 0));
    while (!S.empty()) {
        int vertex = S.front().first;
        int dep = S.front().second;
        S.pop();
        // cout << "ver: " << vertex << ", " << to[vertex] << "\n";
        seen[vertex] = true;
        rep(j, to[vertex].size()) {
            int neighbor = to[vertex][j];
            if (!seen[neighbor]) {
                dist[neighbor] = dep + 1;
                par[neighbor] = vertex;
                S.push(pint(neighbor, dep+1));
                seen[neighbor] = true;
            }
        }
        // cout << "par: " << par << "\n";
    }
}

const int INF = 1001001;
int main()
{
    cin >> n >> m;
    dist = vector<int>(n);
    par = vector<int>(n);
    UnionFind UF(n);
    rep(i,m) {
        int a, b;
        cin >> a >> b;
        a--; b --;
        to[a].push_back(b);
        to[b].push_back(a);
        UF.unite(a, b);
    }
    if (UF.size(0) < n) {
        cout << "No\n";
        return 0;
    }
    bfs(0);
    // cout << dist << "\n";
    // cout << par << "\n";
    cout << "Yes\n";
    repSE(i,1,n) {
        cout << par[i] + 1 << "\n";
    }
    return 0;
}


Measured memory_bytes: 11404