HDU3018 Ant Trip 欧拉路径

来源:互联网 发布:sql numeric和decimal 编辑:程序博客网 时间:2024/04/29 01:06

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3018


题目大意:n个蚂蚁村庄之间有m条道路,一群蚂蚁想要遍历所有的村庄,且每条道路只走一次,问至少需要把这群蚂蚁分成多少组才能实现目标。


分析:我们假设n个村庄之间有k个连通分量,对于每一个连通分量,如果存在欧拉路径,那么该分量需要一组蚂蚁就行;如果不存在欧拉路径,我们知道,要想遍历该分量所有的顶点且每条边只走一次,如果所有的顶点都有偶数个度数,那么就存在欧拉回路了,也只需要一组蚂蚁,如果存在奇数度数的顶点,而且又要想一笔画走完所有边,我们就要从这个顶点开始出发,到另一个奇数度数的顶点为止==>即两个奇数度数的顶点确定一条路径,但该路径并不一定覆盖该连通分量重所有的顶点,对于其他的顶点,我们仍然遵循上面的步骤,这样对于每一个不存在欧拉路径的连通分量,他需要的步数就等于该连通分量中所有奇数度顶点的个数除以2.分别把这些不存在欧拉路径的连通分量的步数加起来,然后再加上存在欧拉路径的步数,就是最终的结果了。


实现代码如下:

#include <cstdio>#include <cstring>#include <iostream>using namespace std;const int maxn=100005;int ind[maxn];bool vis[maxn];int par[maxn],ran[maxn];void init(int n){    for(int i=1;i<=n;i++)    {        par[i]=i;        ran[i]=1;    }}int Find(int x){    if(par[x]!=x)      return par[x]=Find(par[x]);    return x;}void Union(int x,int y){    x=Find(x);    y=Find(y);    if(x==y) return ;    if(ran[x]>ran[y])    {        par[y]=x;        ran[x]+=ran[y];    }    else    {        par[x]=y;        ran[y]+=ran[x];    }}int main(){    int n,m;    while(scanf("%d%d",&n,&m)!=-1)    {        init(n);        int u,v;        memset(ind,0,sizeof(ind));        memset(vis,0,sizeof(vis));        for(int i=0;i<m;i++)        {            scanf("%d%d",&u,&v);            Union(u,v);            ind[u]++;            ind[v]++;        }        for(int i=1;i<=n;i++)          if(par[i]==i) vis[i]=1;        int odd=0,ans=0;        for(int i=1;i<=n;i++)        {            if(ind[i]%2)            {                int x=Find(i);                if(vis[x]) vis[x]=0;                odd++;            }        }        for(int i=1;i<=n;i++)          if(vis[i]&&ind[i]) ans++;        printf("%d\n",ans+odd/2);    }    return 0;}


0 0
原创粉丝点击