HDU 3018 Ant Trip(连通分量 & 欧拉路)

题目链接:Click here~~

题意:

无向图中,不算孤立点,问最少几笔才能画完。

解题思路:

结论:对于每个连通分量,如果不存在奇度点,那么它需要 1 笔。如果存在,那么它需要 奇度点/2 笔。

#include <map>
#include <stdio.h>
#include <string.h>
#include <algorithm>

using namespace std;

namespace UFset
{
    const int N = 1e5 + 5;
    int pre[N];
    void init(){
        memset(pre,-1,sizeof(pre));
    }
    int root(int x){
        return pre[x] == -1 ? x : pre[x] = root(pre[x]);
    }
    bool gather(int a,int b){
        int r1 = root(a);
        int r2 = root(b);
        if(r1 == r2)
            return false;
        else
            pre[r1] = r2;
            return true;
    }
}

using namespace UFset;

int deg[N];

bool EulerTour(int n)       //un-direct
{
    int rt = root(1);
    for(int i=1;i<=n;i++)
        if(root(i) != rt || deg[i] & 1)
            return false;
    return true;
}

int EulerTourCnt(int n)
{
    map<int,int> M;
    for(int i=1;i<=n;i++)
    {
        if(deg[i] == 0)
            continue;
        int rt = root(i);
        if(!M.count(rt))
            M[rt] = 0;
        if(deg[i] & 1)
            M[rt]++;
    }
    int cnt = 0;
    for(map<int,int>::iterator it=M.begin();it!=M.end();it++)
        cnt += (*it).second ? (*it).second/2 : 1;
    return cnt;
}

int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        init();
        memset(deg,0,sizeof(deg));
        for(int i=0;i<m;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            ++deg[u] , ++deg[v];
            gather(u,v);
        }
        printf("%d\n",EulerTourCnt(n));
    }
    return 0;
}


你可能感兴趣的:(HDU 3018 Ant Trip(连通分量 & 欧拉路))