FZU 2112 Tickets

时间:2023-03-09 18:52:58
FZU 2112 Tickets

这个问题可以转变一下,先要知道有几个连通块,连通块之间肯定需要添加一条边,

还需要知道每个连通块内部需要添加几条边,这个问题等价于求一张图至少需要几笔画成,这个问题的答案是度为奇数的点的个数/2

#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std; const int maxn=+;
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=;
memset(tot,,sizeof tot);
memset(flag,,sizeof flag);
memset(flag2,,sizeof flag2);
} void read()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++) G[i].clear();
for(int i=;i<=m;i++)
{
int u,v; scanf("%d%d",&u,&v);
tot[u]++;tot[v]++;
flag2[u]=;flag2[v]=;
G[u].push_back(v);
G[v].push_back(u);
}
} void dfs(int now)
{
flag[now]=; q[sum++]=now;
for(int i=;i<G[now].size();i++)
if(!flag[G[now][i]])
dfs(G[now][i]);
} void work()
{
for(int i=;i<=n;i++)
{
if(!flag[i]&&flag2[i])
{
sum=; ans++; dfs(i);
int tmp=;
for(int j=;j<sum;j++) if(tot[q[j]]%==) tmp++;
ans=ans+(tmp-)/;
}
}
ans--;
printf("%d\n",ans);
} int main()
{
scanf("%d",&T);
while(T--)
{
init();
read();
work();
}
return ;
}