加一条边后 存在欧拉回路
#include<bits/stdc++.h>
#include<string>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
const ll mod=1e9+7;
const int INF=0x3f3f3f3f;
#define pb push_back
#define IO ios::sync_with_stdio(false);cin.tie(0);
int n,m,maxx,kuai,cntt,flag=1; //cnt连通块个数 cntt度为奇数点个数
int a,b;
//无向连通图:所有点度都是偶数,或者恰好有2个点度是奇数,则有欧拉路。若有奇数点度,则奇数点度点一定是欧拉路的起点和终点,否则可取任意一点作为起点
vector<int> g[maxn],cnt[maxn];//存图 存每个连通块度为奇数的点
int vis[maxn],minn[maxn];//连通块内度为偶数最小点
void dfs(int now){ //统计每一块奇数点的个数 两个块的话奇数点个数超过4
vis[now]=1;
if(g[now].size()&1) //这个点度为奇数
{
cntt++;
cnt[kuai].pb(now);
if(cnt[kuai].size()>2) //1个连通块度为奇数点超过2个 比如4
{
flag=0;
}
}
else{ //度为偶数的点 最小
minn[kuai]=min(minn[kuai],now); //此连通块度偶数的最小点
}
for(auto k: g[now]){
if(!vis[k])
dfs(k);
}
}
int main() {
IO;
flag=1;
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>a>>b;
g[a].pb(b);
g[b].pb(a);
}
memset(minn, 0x3f, sizeof minn);//最小点在前面找
for(int i=1;i<=n;i++){
if(g[i].size()>0 && !vis[i]) //不走孤立点 如4未被访问
{
kuai++;
dfs(i);
}
}
if(cntt>4 || (flag==0 && kuai>1) || kuai>2) //2个块其中1个块度为奇数点超过2 不可能给连通块内部加边 再连通2个块加边 度为奇数的点个数4 2
return cout<<"NO"<<endl,0;
cout<<"YES"<<endl;
int ans1=1,ans2=2; //n>=2 起码2个点
//1个kuai 全为偶数点输出1 2
if(kuai==2 && cntt==2) //2个度为奇数的点 肯定在1个块内 1个2个奇数度点 1个0个
{
if(cnt[1].size()>0) {
ans1=min(cnt[1][0],cnt[1][1]);
ans2=minn[2]; //第二块 度为偶数的最小点
}
else { //第二块2个奇数度点
ans1=minn[1];
ans2=min(cnt[2][0],cnt[2][1]);
}
}
else if(kuai==2 && cntt==4) { //分别2个 1-2 3-4 连1-3 走4-3-1-2
ans1=min(cnt[1][0],cnt[1][1]);
ans2=min(cnt[2][0],cnt[2][1]);
}
else if(kuai==1 && cntt==2) { // 1 2 2 3 连度为奇数最小点 和度偶数最小点
ans1=min(cnt[1][0],cnt[1][1]);
//前提是有度为偶数的点 1 2 就无
if(n>2) //构成1个kuai 肯定有度偶数点
ans2=minn[1];
else
ans2=max(cnt[1][0],cnt[1][1]); //1 2
}
else if(kuai==1 && cntt==4) { //十字 1上 2 5 4中 3下 连1-2 连成4-2-1-5-3
sort(cnt[1].begin(),cnt[1].end());
ans1=cnt[1][0];ans2=cnt[1][1];
}
else if(kuai==2 && cntt==0) //1-2 1-2 3-4 3-4 连1-3
{
ans1=minn[1]; //每一个块 度最小的偶数点
ans2=minn[2];
}
cout<<min(ans1,ans2)<<" "<<max(ans1,ans2)<<endl;
return 0;
}