传送机
题目描述
刷完牙洗完脸,黄黄同学就要上课去了。可是黄黄同学每次去上课时总喜欢把校园里面的每条路都走一遍,当然,黄黄同学想每条路也只走一遍。我们一般人很可能对一些地图是办不到每条路走一遍且仅走一遍的,但是黄黄同学有个传送机,他可以任意地将一个、人从一个路口传送到任意一个路口。
可是,每传送一次是需要耗费巨大的内力的,黄黄同学希望可以用最少的传送次数完成游遍校园,你能帮助他吗?
因为黄黄同学只是游历校园,于是我们可以认为黄黄同学可以从任意点开始,到任意点结束。
输入
输入文件sent.in的第一行有一个整数N,表示黄黄的校园里一共有多少路口。
第二行有一个整数M,表示路口之间有M条路。
后面M行每行两个整数a、b表示a与b之间有一条路,且路是双向的。
输出
输出文件sent.out只包括一个整数s,表示黄黄同学最少的传送次数。
样例输入
3 2 1 2 2 3
样例输出
0
提示
对于100%的数据,保证N≤100000,K≤500000,1≤a,b≤N。
#include<bits/stdc++.h> using namespace std; const int N=100001; const int M=500001; struct edge{ int to,nxt; }e[M*2]; int ans,n,m,head[N],cnt,in[N],u,v,sum,dis[N],flag; bool used[N],inq[N]; queue<int> q; inline void add_edge(register int x,register int y) { e[++cnt].nxt=head[x]; e[cnt].to=y; head[x]=cnt; } inline void spfa(register int st) { memset(dis,0x3f,sizeof(dis)); memset(inq,0,sizeof(inq)); inq[st]=1,used[st]=1; dis[st]=0,sum=0; if(in[st]%2==1) sum++; q.push(st); while(!q.empty()) { register int x=q.front(); q.pop(); inq[x]=0; for(register int i=head[x];i;i=e[i].nxt) { register int v=e[i].to; if(dis[x]+1<dis[v]) { dis[v]=dis[x]+1; if(!inq[v]) { if(in[v]%2==1) sum++; inq[v]=1,used[v]=1; q.push(v); } } } } if(sum>2) ans+=sum/2-1; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { scanf("%d%d",&u,&v); add_edge(u,v); add_edge(v,u); in[u]++,in[v]++; } for(int i=1;i<=n;i++) if(used[i]==0&&in[i]!=0) spfa(i),flag++; printf("%d\n",ans+flag-1); return 0; }