此題明顯要求歐拉通路的條數:鑑於無向圖可能不是連通圖,需要求出每個連通塊的歐拉通路。每個塊的歐拉通路求法是根據奇度頂點的個數判斷。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;
}