FZU 2112 Tickets
这个问题可以转变一下,先要知道有几个连通块,连通块之间肯定需要添加一条边,
还需要知道每个连通块内部需要添加几条边,这个问题等价于求一张图至少需要几笔画成,这个问题的答案是度为奇数的点的个数/2
#include<cstdio> #include<cstring> #include<cmath> #include<vector> #include<algorithm> using namespace std; const int maxn=100000+10; int T; int n,m; vector<int>G[maxn]; int tot[maxn]; bool flag[maxn]; bool flag2[maxn]; int q[maxn],sum; int ans; void init() { ans=0; memset(tot,0,sizeof tot); memset(flag,0,sizeof flag); memset(flag2,0,sizeof flag2); } void read() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) G[i].clear(); for(int i=1;i<=m;i++) { int u,v; scanf("%d%d",&u,&v); tot[u]++;tot[v]++; flag2[u]=1;flag2[v]=1; G[u].push_back(v); G[v].push_back(u); } } void dfs(int now) { flag[now]=1; q[sum++]=now; for(int i=0;i<G[now].size();i++) if(!flag[G[now][i]]) dfs(G[now][i]); } void work() { for(int i=1;i<=n;i++) { if(!flag[i]&&flag2[i]) { sum=0; ans++; dfs(i); int tmp=0; for(int j=0;j<sum;j++) if(tot[q[j]]%2==1) tmp++; ans=ans+(tmp-1)/2; } } ans--; printf("%d\n",ans); } int main() { scanf("%d",&T); while(T--) { init(); read(); work(); } return 0; }