Problem:
Score: 400 points

Problem Statement

There is a cave.

The cave has N rooms and M passages. The rooms are numbered 1 to N, and the passages are numbered 1 to M. Passage i connects Room A_i and Room B_i bidirectionally. One can travel between any two rooms by traversing passages. Room 1 is a special room with an entrance from the outside.

It is dark in the cave, so we have decided to place a signpost in each room except Room 1. The signpost in each room will point to one of the rooms directly connected to that room with a passage.

Since it is dangerous in the cave, our objective is to satisfy the condition below for each room except Room 1.

If you start in that room and repeatedly move to the room indicated by the signpost in the room you are in, you will reach Room 1 after traversing the minimum number of passages possible.

Determine whether there is a way to place signposts satisfying our objective, and print one such way if it exists.

Constraints

All values in input are integers.

2 \leq N \leq 10^5

1 \leq M \leq 2 \times 10^5

1 \leq A_i, B_i \leq N\ (1 \leq i \leq M)

A_i \neq B_i\ (1 \leq i \leq M)

One can travel between any two rooms by traversing passages.

Input

Input is given from Standard Input in the following format:

N M
A_1 B_1
:
A_M B_M

Output

If there is no way to place signposts satisfying the objective, print No.

Otherwise, print N lines. The first line should contain Yes, and the i-th line (2 \leq i \leq N) should contain the integer representing the room indicated by the signpost in Room i.

Sample Input 1

4 4
1 2
2 3
3 4
4 2

Sample Output 1

Yes
1
2
2

If we place the signposts as described in the sample output, the following happens:

Starting in Room 2, you will reach Room 1 after traversing one passage: (2) \to 1. This is the minimum number of passages possible.

Starting in Room 3, you will reach Room 1 after traversing two passages: (3) \to 2 \to 1. This is the minimum number of passages possible.

Starting in Room 4, you will reach Room 1 after traversing two passages: (4) \to 2 \to 1. This is the minimum number of passages possible.

Thus, the objective is satisfied.

Sample Input 2

6 9
3 4
6 1
2 4
5 3
4 6
1 5
6 2
4 5
5 6

Sample Output 2

Yes
6
5
5
1
1

If there are multiple solutions, any of them will be accepted.

Solution in C# (.NET Core 3.1.201) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Diagnostics.Tracing;
using System.Linq;
using System.Net.NetworkInformation;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using Extensions;
using DSA;
using static System.Math;
using static Extensions.MathExtension;
using static Extensions.ConsoleInputExtension;
using static Extensions.ConsoleOutputExtension;

class Solver
{
    public void Solve()
    {
        //Solve Code Here
        int n = Cin, m = Cin;
        var nodes = new Node[n];
        for (int i = 0; i < n; i++) nodes[i] = new Node() {Index = i};
        for (int i = 0; i < m; i++) nodes[Cin - 1].AddConnection(nodes[Cin - 1]);
        var q = new PriorityQueue<(Node, int)>();
        nodes[0].MinDist = 0;
        q.Push((nodes[0], 0), 0);
        while (q.Count > 0)
        {
            var node = q.Pop();
            if (node.Item1.MinDist != node.Item2) continue;
            for (var i = 0; i < node.Item1.Connections.Count; i++)
            {
                if (node.Item1.Connections[i].MinDist > node.Item1.MinDist + 1)
                {
                    node.Item1.Connections[i].MinDist = node.Item1.MinDist + 1;
                    node.Item1.Connections[i].PrevIndex = node.Item1.Index;
                    q.Push((node.Item1.Connections[i], node.Item1.MinDist + 1), -(node.Item1.MinDist + 1));
                }
            }
        }

        Coutln("Yes");
        foreach (var node in nodes.Skip(1))
        {
            Coutln(node.PrevIndex + 1);
        }
    }
}

//Other Classes Here
class Node
{
    public int Index { get; set; }
    public int MinDist { get; set; } = int.MaxValue;
    public int PrevIndex { get; set; } = -1;
    public List<Node> Connections { get; } = new List<Node>();

    public void AddConnection(Node n)
    {
        n.Connections.Add(this);
        this.Connections.Add(n);
    }
}

#if !DEBUG
class EntryPoint
{
    static void Main(string[] args)
    {
        new Solver().Solve();
        Flush();
    }
}
#endif


namespace DSA
{
    /// <summary>
    /// 二分ヒープによる優先度付きキュー
    /// </summary>
    /// <typeparam name="T">内部に格納するデータ型</typeparam>
    public class PriorityQueue<T>
    {
        private readonly List<Tuple<int, T>> _list = new List<Tuple<int, T>>();

        public int Count => _list.Count;

        public PriorityQueue()
        {
        }

        /// <summary>
        /// 要素をひとつ入力する
        /// O(logN)
        /// </summary>
        /// <param name="item">要素</param>
        /// <param name="priority">優先度</param>
        public void Push(T item, int priority)
        {
            _list.Add(Tuple.Create(priority, item));

            int itemIndex = Count - 1, parentIndex;
            while ((parentIndex = GetParentIndex(itemIndex)) != -1 &&
                   priority                                  > _list[parentIndex].Item1)
            {
                Swap(itemIndex, parentIndex);
                itemIndex = parentIndex;
            }
        }

        private int GetParentIndex(int index)
        {
            if (index == 0) return -1;
            return ((index + 1) >> 1) - 1;
        }

        private Tuple<int, int> GetChildrenIndex(int index)
        {
            var item2 = (index + 1) << 1;
            var item1 = item2 - 1;
            return Tuple.Create(item1, item2);
        }

        /// <summary>
        /// 優先度の一番大きい要素を取得し削除する
        /// O(logN)
        /// </summary>
        /// <returns>優先度の一番大きい要素</returns>
        /// <exception cref="IndexOutOfRangeException">キューが空だった場合</exception>
        public T Pop()
        {
            if (Count <= 0) throw new IndexOutOfRangeException();
            var item = _list[0].Item2;
            _list[0] = _list[Count - 1];
            _list.RemoveAt(Count - 1);

            int index = 0;
            Tuple<int, int> childrenIndex = GetChildrenIndex(index);
            while (childrenIndex.Item1 < Count || childrenIndex.Item2 < Count)
            {
                if (childrenIndex.Item2 >= Count || _list[childrenIndex.Item1].Item1 > _list[childrenIndex.Item2].Item1)
                {
                    if (_list[childrenIndex.Item1].Item1 <= _list[index].Item1) return item;

                    Swap(index, childrenIndex.Item1);
                    index = childrenIndex.Item1;
                }
                else
                {
                    if (_list[childrenIndex.Item2].Item1 <= _list[index].Item1) return item;
                    Swap(index, childrenIndex.Item2);
                    index = childrenIndex.Item2;
                }

                childrenIndex = GetChildrenIndex(index);
            }

            return item;
        }

        /// <summary>
        /// 優先度の一番大きい要素を取得する(削除はしない)
        /// O(1)
        /// </summary>
        /// <returns>優先度の一番大きい要素</returns>
        public T Peek()
        {
            return _list[0].Item2;
        }

        private void Swap(int index1, int index2)
        {
            var tmp = _list[index1];
            _list[index1] = _list[index2];
            _list[index2] = tmp;
        }
    }

    /// <summary>
    /// マージをサポートするUnionFind木
    /// </summary>
    public class UnionFind
    {
        private readonly int[] _array;

        /// <summary>
        /// 要素数を指定しUnionFind木を初期化する
        /// O(N)
        /// </summary>
        /// <param name="size">UnionFind木の要素数</param>
        public UnionFind(int size)
        {
            _array = new int[size];
            for (int i = 0; i < size; i++)
            {
                _array[i] = i;
            }
        }

        private int GetRootNode(int n)
        {
            if (_array[n] == n) return n;
            return _array[n] = GetRootNode(_array[n]);
        }

        /// <summary>
        /// ふたつの要素が所属するグループを併合する
        /// O(α(N))
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        public void UnionGroup(int a, int b)
        {
            var rootA = GetRootNode(a);
            var rootB = GetRootNode(b);
            if (rootA == rootB) return;
            _array[rootA] = rootB;
        }

        /// <summary>
        /// ふたつの要素が同じグループに所属するかを確かめる
        /// O(α(N))
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns>ふたつの要素が同じグループに所属する⇔true</returns>
        public bool IsSameGroup(int a, int b) => GetRootNode(a) == GetRootNode(b);
    }

    public delegate T SegTreeCombiner<T>(T item1, T item2);

    public class SegTree<T>
    {
        private readonly T _defaultItem;
        private readonly SegTreeCombiner<T> _func;
        private T[] List;
        private int size;

        public SegTree(T[] list, T defaultItem, SegTreeCombiner<T> func)
        {
            _defaultItem = defaultItem;
            _func = func;
            size = 1;
            while (size < list.Length) size <<= 1;
            List = new T[2 * size - 1];
            for (int i = 0; i           < list.Length; i++) List[i + size - 1] = list[i];
            for (int i = list.Length; i < size; i++) List[i        + size - 1] = defaultItem;
            for (int i = size - 1 - 1; i >= 0; i--)
            {
                List[i] = _func(List[2 * i + 1], List[2 * i + 2]);
            }
        }

        public void Update(int index, T value)
        {
            index += size - 1;
            List[index] = value;
            while (index > 0)
            {
                index = (index - 1) >> 1;
                List[index] = _func(List[2 * index + 1], List[2 * index + 2]);
            }
        }

        public T Query(int a, int b)
        {
            return Query(a, b, 0, 0, size);
        }

        private T Query(int a, int b, int k, int l, int r)
        {
            if (r <= a || b <= l) return _defaultItem;
            if (a <= l && r <= b) return List[k];
            return _func(Query(a, b, k * 2 + 1, l, (l + r) >> 1), Query(a, b, k * 2 + 2, (l + r) >> 1, r));
        }
    }

    public static class BinarySearch
    {
        public delegate bool Terms<T>(T i);

        public static int UpperBound(int initLeft, int initRight, Terms<int> term)
        {
            //TODO:範囲内に条件を満たす区間が存在しない場合に対応する
            int left = initLeft - 1, right = initRight;
            while (right - left > 1)
            {
                int mid = (left + right) >> 1;
                if (mid != initLeft - 1 && term(mid)) left = mid;
                else right = mid;
            }

            return left;
        }

        public static long UpperBound(long initLeft, long initRight, Terms<long> term)
        {
            long left = initLeft - 1, right = initRight;
            while (right - left > 1)
            {
                long mid = (left + right) >> 1;
                if (mid != initLeft - 1 && term(mid)) left = mid;
                else right = mid;
            }

            return left;
        }

        public static int LowerBound(int initLeft, int initRight, Terms<int> term)
        {
            int left = initLeft - 1, right = initRight;
            while (right - left > 1)
            {
                int mid = (left + right) >> 1;
                if (mid != initRight && term(mid)) right = mid;
                else left = mid;
            }

            return right;
        }

        public static long LowerBound(long initLeft, long initRight, Terms<long> term)
        {
            long left = initLeft - 1, right = initRight;
            while (right - left > 1)
            {
                long mid = (left + right) >> 1;
                if (term(mid)) right = mid;
                else left = mid;
            }

            return right;
        }
    }
}


struct ModInt
{
    public long Value { get; }
    public static long Mod { get; set; } = 1000000000L + 7;

    public ModInt(long l)
    {
        long value = l % Mod;
        while (value < 0) value += Mod;
        Value = value % Mod;
    }

    public static implicit operator long(ModInt m)
    {
        return m.Value;
    }

    public static implicit operator ModInt(long l)
    {
        return new ModInt(l);
    }

    public static ModInt operator +(ModInt a, ModInt b)
    {
        return new ModInt(a.Value + b.Value);
    }

    public static ModInt operator -(ModInt a, ModInt b)
    {
        return new ModInt(a.Value - b.Value);
    }

    public static ModInt operator *(ModInt a, ModInt b)
    {
        return new ModInt(a.Value * b.Value);
    }

    public static ModInt operator /(ModInt a, ModInt b)
    {
        return new ModInt(a * b.Inverse());
    }

    public override string ToString()
    {
        return Value.ToString();
    }
}

static class ModIntMath
{
    public static ModInt Pow(this ModInt a, ModInt b)
    {
        var pow = b.Value;
        var m = a;
        ModInt ans = new ModInt(1);
        while (pow != 0)
        {
            if ((pow & 1) == 1)
            {
                ans *= m;
            }

            pow >>= 1;
            m *= m;
        }

        return ans;
    }

    public static ModInt Inverse(this ModInt m)
    {
        return m.Pow((ModInt) (ModInt.Mod - 2));
    }
}


namespace Extensions
{
    public class ConsoleInputExtension
    {
        private static readonly ConsoleInputExtension _cin = new ConsoleInputExtension();

        public static ConsoleInputExtension Cin => _cin;

        private static readonly Queue<string> _inputQueue = new Queue<string>();

        private ConsoleInputExtension()
        {
        }

        public static implicit operator string(ConsoleInputExtension _)
        {
            if (_inputQueue.Count == 0)
                Console.ReadLine().Split(' ')
                       .ForEach(val => _inputQueue.Enqueue(val));
            return _inputQueue.Dequeue();
        }

        public static implicit operator int(ConsoleInputExtension _)
        {
            if (_inputQueue.Count == 0)
                Console.ReadLine().Split(' ')
                       .ForEach(val => _inputQueue.Enqueue(val));
            return int.Parse(_inputQueue.Dequeue());
        }

        public static implicit operator long(ConsoleInputExtension _)
        {
            if (_inputQueue.Count == 0)
                Console.ReadLine().Split(' ')
                       .ForEach(val => _inputQueue.Enqueue(val));
            return long.Parse(_inputQueue.Dequeue());
        }

        public static implicit operator float(ConsoleInputExtension _)
        {
            if (_inputQueue.Count == 0)
                Console.ReadLine().Split(' ')
                       .ForEach(val => _inputQueue.Enqueue(val));
            return float.Parse(_inputQueue.Dequeue());
        }

        public static implicit operator double(ConsoleInputExtension _)
        {
            if (_inputQueue.Count == 0)
                Console.ReadLine().Split(' ')
                       .ForEach(val => _inputQueue.Enqueue(val));
            return double.Parse(_inputQueue.Dequeue());
        }
    }

    public static class ConsoleOutputExtension
    {
        private static StringBuilder _builder = new StringBuilder();

        public static void Cout(object o)
        {
            _builder.Append(o);
        }

        public static void CoutF(object o)
        {
            _builder.Append(o);
            Flush();
        }

        public static void Coutln(object o)
        {
            _builder.Append(o);
            _builder.Append('\n');
        }

        public static void Coutln()
        {
            _builder.Append('\n');
        }

        public static void CoutlnF(object o)
        {
            _builder.Append(o);
            _builder.Append('\n');
            Flush();
        }

        public static void Flush()
        {
            Console.Write(_builder.ToString());
            _builder.Clear();
        }
    }

    public static class MathExtension
    {
        //最小公倍数
        public static int LCM(int num1, int num2)
        {
            var gcd = GCD(num1, num2);
            return num1 * (num2 / gcd);
        }

        public static long LCM(long num1, long num2)
        {
            var gcd = GCD(num1, num2);
            return num1 * (num2 / gcd);
        }

        //最大公約数
        public static int GCD(int num1, int num2)
        {
            int a = Math.Max(num1, num2);
            int b = Math.Min(num1, num2);
            if (b == 0) return a;
            int mod;
            while ((mod = a % b) != 0)
            {
                a = b;
                b = mod;
            }

            return b;
        }

        public static long GCD(long num1, long num2)
        {
            long a = Math.Max(num1, num2);
            long b = Math.Min(num1, num2);
            if (b == 0) return a;
            long mod;
            while ((mod = a % b) != 0)
            {
                a = b;
                b = mod;
            }

            return b;
        }
    }

    public static class EnumerableExtension
    {
        public delegate void Function<in T>(T val);

        public static void ForEach<T>(this IEnumerable<T> enumerable, Function<T> function)
        {
            foreach (var x in enumerable)
            {
                function(x);
            }
        }
    }
}