传送机

题目描述

刷完牙洗完脸,黄黄同学就要上课去了。可是黄黄同学每次去上课时总喜欢把校园里面的每条路都走一遍,当然,黄黄同学想每条路也只走一遍。我们一般人很可能对一些地图是办不到每条路走一遍且仅走一遍的,但是黄黄同学有个传送机,他可以任意地将一个、人从一个路口传送到任意一个路口。

可是,每传送一次是需要耗费巨大的内力的,黄黄同学希望可以用最少的传送次数完成游遍校园,你能帮助他吗?

因为黄黄同学只是游历校园,于是我们可以认为黄黄同学可以从任意点开始,到任意点结束。

输入

输入文件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;
}
posted @ 2020-06-20 18:35  牛大了的牛大  阅读(204)  评论(0编辑  收藏  举报