解析
本题是一道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_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
memset(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
*/