题意:拓展一笔画问题。给一个无向图,每条边只能经过一次,问多少笔能将图画完。孤立的点不用考虑。
思路:先把每个连通分量找出来,然后数这个连通分量的度为奇数的点,如果该连通分量是欧拉通路,显然可以一笔画,否则需要次数是奇度点数量/2。
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <string>
#include <memory.h>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <ctype.h>
#define ll long long
#define max3(a,b,c) max(a,max(b,c))
using namespace std;
vector<int> mp[100010];
int deg[100010];
int p[100010];//标记连通分量
int odd[100010];
int main(){
int n,m;
while(cin>>n>>m){
//init
memset(p,-1,sizeof(p));
memset(mp,0,sizeof(mp));
memset(deg,0,sizeof(deg));
memset(odd,0,sizeof(odd));
//
for(int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
deg[u]++; deg[v]++;
mp[u].push_back(v);
mp[v].push_back(u);
}
int cnt=0;
for(int i=1;i<=n;i++){
if(p[i]==-1){
if(!deg[i])continue;//无视孤立的点
cnt++;
p[i]=cnt;
}else{
continue;
}
queue<int> que; que.push(i);
while(!que.empty()){
int cur=que.front(); que.pop();
int siz=mp[cur].size();
for(int j=0;j<siz;j++){
int v=mp[cur][j];
if(p[v]!=-1)continue;
que.push(v);
p[v]=cnt;
}
}
}
for(int i=1;i<=n;i++){
if(deg[i]&1){
odd[p[i]]++;
}
}
int ans=0;
for(int i=1;i<=cnt;i++){
ans+=max(1,(odd[i]/2));
}
cout<<ans<<endl;
}
return 0;
}