对于一个连通图而言,有这样的一个性质:其需要画的笔数=度数为奇数的点数除以2
有了这个结论,用并查集求联通块就行
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> using namespace std; const int maxn=100005; int father[maxn]; int indegree[maxn]; int n,m; int a[maxn]; void init(){ for(int i=1;i<=n;i++) father[i]=i; } int find(int u){ if(father[u]!=u) father[u]=find(father[u]); return father[u]; } void Union(int x,int y){ int t1=find(x); int t2=find(y); if(t1!=t2) father[t1]=t2; } int main(){ while(scanf("%d%d",&n,&m)!=EOF){ init(); // memset(father,0,sizeof(father)); memset(indegree,0,sizeof(indegree)); memset(a,-1,sizeof(a)); for(int i=1;i<=m;i++){ int u,v; scanf("%d%d",&u,&v); indegree[u]++; indegree[v]++; Union(u,v); } for(int i=1;i<=n;i++){ int t=find(i); if(a[t]==-1&&indegree[i]>0) a[t]=0; if(indegree[i]&1) a[t]++; } int ans=0; for(int i=1;i<=n;i++){ if(a[i]==0) ans++; else if(a[i]>0) ans+=a[i]/2; } printf("%d ",ans); } return 0; }