此题明显要求欧拉通路的条数:鉴于无向图可能不是连通图,需要求出每个连通块的欧拉通路。每个块的欧拉通路求法是根据奇度顶点的个数判断。d==0||d==2则存在一条欧拉回路或欧拉通路。否则有d/2条欧拉通路。但是要特判一个仅有一个顶点的连通块,此情况不存在欧拉通路。
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <vector>
#include <map>
#include <queue>
#include <cstdio>
#include <string>
#include <stack>
#include <set>
#define IOS ios::sync_with_stdio(false), cin.tie(0)
using namespace std;
typedef long long ll;
int d[200010];//d[i]=n;表示i号顶点的度为n
int du[200010];//du[cnt]=n;表示块号为cnt的连通块有奇度顶点n个
int f[200010];//f[i];i号顶点的根节点
int c[200010];//c[i]=x;表示i号顶点在块号x中
int cnt=0;//连通块号
int find(int x){
int r=x;
while(r!=f[r]){
r=f[r];
}
int j=x;
while(f[j]!=r){
f[j]=r;
j=f[x];
x=j;
}
return r;
}
int main()
{
IOS;
int n,m,x,y;
cin>>n>>m;
for(int i=1;i<=n;i++){
f[i]=i;
}
//并查集
for(int i=1;i<=m;i++){
cin>>x>>y;
d[x]++;d[y]++;
int tx=find(x);
int ty=find(y);
if(tx!=ty){
if(tx<ty)f[ty]=tx;
else f[tx]=ty;
}
}
for(int i=1;i<=n;i++){
if(find(i)==i){
if(d[i]==0)continue;
c[i]=cnt++;//对连通块号离散化
}
du[c[f[i]]]+=d[i]&1?1:0;//对i号点所在的块的奇度顶点统计
}
ll ans=0;
for(int i=0;i<cnt;i++){//遍历每一个块
if(du[i]==0||du[i]==2)ans+=1;//存在一条欧拉通路
else ans+=du[i]/2;//存在du[i]/2条欧拉通路
}
if(ans==1)cout<<"YES"<<endl;
else {
cout<<"NO"<<endl;
cout<<ans<<endl;
}
getchar();
getchar();
return 0;
}