HDU3018 Ant Trip 欧拉路径

题目链接: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;
}


你可能感兴趣的:(HDU3018 Ant Trip 欧拉路径)