解析
本题是一道if的板子题
抓住关键:使所有点的度数全变为2
首先对于度数大于2的点,把它分为若干2度点(和可能的一个单点)
现在我们只剩下单点和二度点了
接下来分来讨论一下
若有多个连通块,我们要把它们变成链再拼起来
所以我们要把所有连通块的各自的单点拚到只剩下一个
最后把所有链拼起来
若只有一个连通块,把所有的1度点合并即可
对于0的处理:开一个新点
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e5+1050;
const double eps=1e-6;
inline ll read(){ll x=0,f=1;char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return f*x;
}
int n,m;
struct node{int to,nxt;
}p[N*10];
int fi[N],cnt;
inline void addline(int x,int y){p[++cnt]={y,fi[x]};fi[x]=cnt;return;
}
int du[N];
int ans,num;
bool vis[N],f;
void dfs(int x){if(vis[x]) return;vis[x]=1;if(du[x]>2) ++ans,f=1;num+=(du[x]&1);for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;dfs(to);}return;
}
int sum,flag,flag2;
int main(){#ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout);#endifmemset(fi,-1,sizeof(fi));cnt=-1;n=read();m=read();for(int i=1;i<=m;i++){int x=read(),y=read();if(!x) x=++n;if(!y) y=++n;du[x]++;du[y]++;addline(x,y);addline(y,x);}for(int i=1;i<=n;i++){if(!vis[i]&&du[i]){num=0;f=0;flag++;dfs(i);if(num>0)ans+=(num)/2-1;else ans+=f?0:1;}}if(flag==1){if(num>0)ans-=(num)/2-1;else ans-=f?0:1;ans=ans+num/2;}if(flag>1) ans+=flag;printf("%d\n",ans);return 0;
}
/*
4a
1 2
2 3
1 3
3 4
*/