// Original C++ solution (slower):
/*

    BFS(bread-first search，幅優先探索)を用いる

    アリ本pp.87以降にグラフの解説がある

*/

#include <stdio.h>

#include <iostream>

#include <vector>

#include <algorithm>

#define _USE_MATH_DEFINES

#include <math.h>

#include <cmath>

using namespace std;



#define repeat(i, n) for (int i = 0; i < (n); i++)

#include<queue>



const int INF = 1001001001;

// vector<int>の配列

// なんでこんなことしてるの...？

vector<int> to[100005];



int main(void)

{

    // 部屋数N、通路数M

    int N, M;

    cin >> N >> M;



    repeat(i, M){

        // 互いに通行可能な部屋a-b

        int a, b;

        cin >> a >> b;

        // 配列格納用にデクリメント処理

        a--;

        b--;

        to[a].push_back(b);

        to[b].push_back(a);

    }



    queue<int> q;

    vector<int> dist(N, INF);   // 無限大で初期化

    vector<int> pre(N, -1); // -1で初期化

    dist[0] = 0;

    q.push(0);

    while (!q.empty())

    {

        int v = q.front();  // 先頭要素の確認

        q.pop();    // 取り出し(上のと一緒くたにできないの...?)

        // 拡張for文(だっけ？)

        for (int u : to[v])

        {

            // 既に距離が算出されていれば以降の処理を省く

            if (dist[u] != INF)

            {

                continue;

            }

            // 繋がっている部屋のゴールまでの距離+1がゴールまでの距離

            dist[u] = dist[v] + 1;

            // 道しるべの部屋番号を記録

            pre[u] = v;

            // キューに自身を格納(幅優先探索の処理、これに基づいて子を展開する)

            q.push(u);

        }

    }



    puts("Yes");

    repeat(i, N){

        if (i == 0){

            continue;

        }

        int ans = pre[i];

        printf("%d\n", ans+1);

    }



    return 0;

}

// Optimized solution to the same problem (faster):
/*

    BFS(bread-first search，幅優先探索)を用いる

    アリ本pp.87以降にグラフの解説がある

*/

#include <stdio.h>

#include <iostream>

#include <vector>

#include <algorithm>

#define _USE_MATH_DEFINES

#include <math.h>

#include <cmath>

using namespace std;



#define repeat(i, n) for (int i = 0; i < (n); i++)

#include<queue>

const int INF = numeric_limits<int>::infinity();



int main(void)

{

    // 部屋数N、通路数M

    int N, M;

    cin >> N >> M;



    vector<vector<int>> to(N, vector<int>());

    repeat(i, M){

        // 互いに通行可能な部屋a-b

        int a, b;

        cin >> a >> b;

        // 配列格納用にデクリメント処理

        a--;

        b--;

        to[a].push_back(b);

        to[b].push_back(a);

    }



    queue<int> q;               // プライオリティキュー使おうと思ったけどBFSできなくなるっぽい

    vector<int> dist(N, INF);   // 無限大で初期化

    vector<int> pre(N, -1);     // -1で初期化

    dist[0] = 0;

    q.push(0);

    while (!q.empty())

    {

        int v = q.front();  // 先頭要素の確認、抜き取り

        q.pop();    // 取り出し(pop()はvoid型だった)

        // 拡張for文(だっけ？)

        for (int u : to[v])

        {

            // 既に距離が算出されていれば以降の処理を省く

            if (dist[u] != INF)

            {

                continue;

            }

            // 繋がっている部屋のゴールまでの距離+1がゴールまでの距離

            dist[u] = dist[v] + 1;

            // 道しるべの部屋番号を記録

            pre[u] = v;

            // キューに自身を格納(幅優先探索の処理、これに基づいて子を展開する)

            q.push(u);

        }

    }



    puts("Yes");

    repeat(i, N){

        if (i == 0){

            continue;

        }

        int ans = pre[i];

        printf("%d\n", ans+1);

    }



    return 0;

}

// Fastest known solution for this problem: