#if __has_include("noamoa_atcoder_lib.h")
#include "noamoa_atcoder_lib.h"
#else
#define _USE_MATH_DEFINES
#include <bits/stdc++.h>
#define endl '\n'
#define all(x) (x).begin(),(x).end()
namespace atcoder {
	using namespace std;
	using ll = long long;

	constexpr ll MOD7 = 1000000007;
	constexpr ll MOD9 = 1000000009;
	constexpr ll LL_MAX = INT64_MAX;
	constexpr ll LL_MIN = INT64_MIN;

	void reverse(string& s){
		reverse(all(s));
	}

	template<typename T>
	void init(vector<T>& v, T initVal = T()){
		for(auto& e : v){
			e = initVal;
		}
	}

	template<typename T>
	void sort(vector<T>& v){
		sort(all(v));
	}
	template<typename T>
	void sortInv(vector<T>& v){
		sort(all(v), greater<T>());
	}

	/* ソートされている必要あり */
	template<typename T>
	int findFirst(const vector<T>& v, const T& val){ 
		const auto it = lower_bound(v.begin(), v.end(), val);
		if(it == v.end() || *it != val) return -1;
		else return it - v.begin();
	}

	/* ソートされている必要あり */
	template<typename T>
	int findLast(const vector<T>& v, const T& val){ 
		auto it = upper_bound(v.begin(), v.end(), val);
		if(it == v.begin()) return -1;
		--it;
		if(*it != val) return -1;
		else return it - v.begin();
	}

	template<typename T>
	void reverse(vector<T>& v){
		reverse(all(v));
	}

	template<typename T>
	T sum(const vector<T>& v){
		T ret = 0;
		for(const auto& e : v) ret += e;
		return ret;
	}

	template<typename T>
	inline vector<T>& operator+=(vector<T>& v, const T& e){
		v.push_back(e);
		return v;
	}

	template<typename T1, typename T2>
	inline vector<T1>& operator+=(vector<T1>& v1, const vector<T2>& v2){
		for(const auto& e : v2) v1.push_back(e);
		return v1;
	}

	template<typename T>
	void in(vector<T>& v){
		for(auto& e : v) cin >> e;
	}

	template<typename T1, typename T2>
	void in(vector<T1>& v1, vector<T2>& v2){
		for(int i=0;i<v1.size();i++)
			cin >> v1[i] >> v2[i];
	}
	template<typename T1, typename T2, typename T3>
	void in(vector<T1>& v1, vector<T2>& v2, vector<T3>& v3){
		for(int i=0;i<v1.size();i++)
			cin >> v1[i] >> v2[i] >> v3[i];
	}
	template<typename T1, typename T2, typename T3, typename T4>
	void in(vector<T1>& v1, vector<T2>& v2, vector<T3>& v3, vector<T4>& v4){
		for(int i=0;i<v1.size();i++)
			cin >> v1[i] >> v2[i] >> v3[i] >> v4[i];
	}

	template<typename T>
	istream& operator>>(istream &stream, vector<T>& v){
		for(auto& e : v) stream >> e;
		return stream;
	}

	template<typename T>
	void out(const vector<T>& v){
		for(const auto& e : v) cout << e << ' ';
		cout << endl;
	}

	template<typename T>
	void outln(const vector<T>& v){
		for(const auto& e : v) cout << e << endl;
	}

	template<typename T>
	inline set<T>& operator+=(set<T>& v, const T& e){
		v.insert(e);
		return v;
	}

	template<typename T1, typename T2>
	inline set<T1>& operator+=(set<T1>& v1, const set<T2>& v2){
		for(const auto& e : v2) v1.insert(e);
		return v1;
	}

	template<typename T1, typename T2>
	class HashTable : public unordered_map<T1, T2>{
		using unordered_map<T1, T2>::unordered_map;

	public:
		constexpr bool contains(const T1& key) const{
			return (*this).find(key) != (*this).end();
		}
	};

	// constexprなswap
	template<typename T>
	constexpr void swap(T& a, T& b) noexcept {
		T t = a;
		a = b;
		b = t;
	}
 
	constexpr ll modPow(ll x, ll n, ll m){ // O(logn)
		if(n == 0) return 1;
		else if(n % 2 == 0) return modPow((x * x) % m, n / 2, m);
		else return x * modPow(x, n - 1, m) % m;
	}

	// 階乗
	class FactorialTable{
		private:
		array<ll, 21> table = {};

		public:
		constexpr FactorialTable(){
			table[0] = 1;
			for(int i=1;i<=20;i++){
				table[i] = i * table[i-1];
			}
		}

		constexpr ll operator[](int n) const {
			if(n < 0) return 0;
			else if(n > 20) return LL_MAX;
			else return table[n];
		}
	};
	constexpr FactorialTable factTable;
	constexpr ll fact(ll n){
		return factTable[n];
	}

	// オイラーのφ関数
	HashTable<ll, ll> phiTable;
	ll phi(ll n){
		if(phiTable.contains(n)){
			return phiTable[n];
		}
		else{
			const ll tmp = n;
			ll ret = n;
			for(ll i=2;i*i<=n;i++){
				if(n % i == 0){
					ret -= ret / i;
					while(n % i == 0) n /= i;
				}
			}
			if(n > 1) ret -= ret / n;
			phiTable[tmp] = ret;
			return ret;
		}
	}

	bool isPrime(ll n){
		return phi(n) == n - 1;
	}

	ll modInv(ll a, ll m){
		return modPow(a, phi(m) - 1, m);
	}

	/* 参考 : https://qiita.com/drken/items/3b4fdf0a78e7a138cd9a */
	// Combination
	struct CombTable{
		ll mod;
		vector<ll> fac, finv, inv;
		CombTable(ll mod_, ll size = 510000){
			mod = mod_;
			fac = vector<ll>(size);
			finv = vector<ll>(size);
			inv = vector<ll>(size);
			fac[0] = fac[1] = 1;
			finv[0] = finv[1] = 1;
			inv[0] = 0, inv[1] = 1;

			for (int i = 2; i < size; i++){
				fac[i] = fac[i - 1] * i % mod;
				inv[i] = mod - inv[mod%i] * (mod / i) % mod;
				finv[i] = finv[i - 1] * inv[i] % mod;
			}
		}
		ll get(int n, int k){
			if (n < k) return 0;
			if (n < 0 || k < 0) return 0;
			return fac[n] * (finv[k] * finv[n - k] % mod) % mod;
		}
	};
	// Mod Int
	template<int MOD> struct Fp {
		ll val;
		constexpr Fp(ll v = 0) noexcept : val(v % MOD) {
			if (val < 0) val += MOD;
		}
		constexpr int getmod() { return MOD; }
		constexpr Fp operator - () const noexcept {
			return val ? MOD - val : 0;
		}
		constexpr Fp operator + (const Fp& r) const noexcept { return Fp(*this) += r; }
		constexpr Fp operator - (const Fp& r) const noexcept { return Fp(*this) -= r; }
		constexpr Fp operator * (const Fp& r) const noexcept { return Fp(*this) *= r; }
		constexpr Fp operator / (const Fp& r) const noexcept { return Fp(*this) /= r; }
		constexpr Fp& operator += (const Fp& r) noexcept {
			val += r.val;
			if (val >= MOD) val -= MOD;
			return *this;
		}
		constexpr Fp& operator -= (const Fp& r) noexcept {
			val -= r.val;
			if (val < 0) val += MOD;
			return *this;
		}
		constexpr Fp& operator *= (const Fp& r) noexcept {
			val = val * r.val % MOD;
			return *this;
		}
		constexpr Fp& operator /= (const Fp& r) noexcept {
			ll a = r.val, b = MOD, u = 1, v = 0;
			while (b) {
				ll t = a / b;
				a -= t * b; swap(a, b);
				u -= t * v; swap(u, v);
			}
			val = val * u % MOD;
			if (val < 0) val += MOD;
			return *this;
		}
		constexpr bool operator == (const Fp& r) const noexcept {
			return this->val == r.val;
		}
		constexpr bool operator != (const Fp& r) const noexcept {
			return this->val != r.val;
		}
		friend constexpr ostream& operator << (ostream &os, const Fp<MOD>& x) noexcept {
			return os << x.val;
		}
		friend constexpr Fp<MOD> modpow(const Fp<MOD> &a, ll n) noexcept {
			if (n == 0) return 1;
			auto t = modpow(a, n / 2);
			t = t * t;
			if (n & 1) t = t * a;
			return t;
		}
	};
}
using namespace atcoder;
#endif

int main(){
	cout << fixed << setprecision(20);




	/*int A,B,H,M;cin>>A>>B>>H>>M;

	int t1 = 60*H+M;
	int t2 = 120*M;
	double t = (t2-t1)*M_PI/360;
	double x1 = A*cos(t), y1 = A*sin(t), x2 = B, y2 = 0;
	
	cout << sqrt((double)((A*cos(t)-B)*(A*cos(t)-B) + A*A*sin(t)*sin(t)));*/

	ll N,M;cin>>N>>M;
	vector<ll> A(M+1),B(M+1);
	for(int i=1;i<=M;i++)cin>>A[i]>>B[i];

	vector<set<ll>> path(N+1);
	for(int i=1;i<=M;i++){
		path[A[i]] += B[i];
		path[B[i]] += A[i];
	}
	
	set<ll> found;
	vector<ll> ans(N+1, 0);
	vector<ll> minDist(N+1, LL_MAX);
	ans[1] = 0, minDist[1] = 0;
	vector<ll> v{1};
	set<ll> next;
	while(found.size() < N){

		bool updated = false;

		for(ll i : v){
			for(ll p : path[i]){
				updated = true;
				//cout << "path : " << i << ", " << p << " : ";
				if(minDist[p] > minDist[i] + 1){
					minDist[p] = minDist[i] + 1;
					ans[p] = i;
					next += p;
				}
				
				found += p;
				//cout << "ans = " << ans[p] << ", minDist = " << minDist[p] <<endl;
			}
		}
		//cout << found.size()<<endl;
		v.clear();
		for(ll e : next){
			v += e;
		}
		next.clear();

		if(!updated){
			cout << "No";
			return 0;
		}
	}

	cout << "Yes" << endl;
	for(int i=2;i<=N;i++){
		cout << ans[i] << endl;
	}
	
}

Measured memory_bytes: 41692