hdu 3018Ant Trip(一笔画问题,用并查集就无向图的连通分量)

1.题意:给一个无向简单图,问至少几笔画画完所有的边。

2.思路:①先用并查集求出有几个连通分量;②如果连通分量中只有一个结点,那么就是0笔画;③在一个简单无向连通图中,如果没有欧拉回路,至少要用n/2笔画画完所有边,n是奇点个数。

3AC代码一(93ms):

#include
#include
#include
#include
using namespace std;

int n,m;
int father[100005];
int deg[100005];//每个结点的度
int vis[100005];
int odd_cnt[100005];
vector vec;

int Find(int a)
{
    int r=a;
    while(father[a]!=a)
    {
        a=father[a];
    }
    father[r]=a;
    return a;
}

inline void Union(int a,int b)
{
    a=Find(a);
    b=Find(b);//千万不要写成father[b]啊啊啊!!!!!!!!!!!!!!!!1
    if(a!=b)
    {
        father[b]=a;
    }
}

int main()
{
    int ans;
    while(scanf("%d%d",&n,&m)==2)
    {
        ans=0;
        vec.clear();
        for(int i=1; i<=n; i++)
        {
            father[i]=i;
            deg[i]=0;
            vis[i]=0;
            odd_cnt[i]=0;
        }
        for(int i=0; i

AC代码二(156ms):

#include
#include
#include
using namespace std;

struct Node
{
    int num;
    set st;
    void init()
    {
        num=0;
        st.clear();
    }
};

int n,m;
int father[100005];
Node son[100005];//结点i的儿子的个数son[i].num,然后装在集合st里
int deg[100005];//每个结点的度



int Find(int a)
{
    int r=a;
    while(father[a]!=a)
    {
        a=father[a];
    }
    father[r]=a;
    return a;
}

void Union(int a,int b)
{
    a=Find(a);
    b=Find(b);
    if(a!=b)
    {
        father[b]=a;
    }
}

int main()
{
    int ans;
    while(scanf("%d%d",&n,&m)==2)
    {
        ans=0;
        for(int i=1; i<=n; i++)
        {
            father[i]=i;
            //son[i]=0;
            deg[i]=0;
            son[i].init();
        }
        for(int i=0; i=2)
            {
                set::iterator it;
                int cnt=0;
                for(it=son[i].st.begin(); it!=son[i].st.end(); it++)
                {
                    if(deg[*it]%2)
                        cnt++;
                }
                if(!cnt)
                    ans+=1;
                else
                    ans=ans+cnt/2;//在一个简单无向连通图中,至少要用n/2笔画画完所有边,n是奇点个数
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

AC代码三(78ms):

#include
#include
#include
using namespace std;

struct Node
{
    int son_num;
    int odd_son_num;
    void init()
    {
        son_num=0;
        odd_son_num=0;
    }
};

int n,m;
int father[100005];
Node son[100005];//结点i的奇点儿子的个数son[i]
int deg[100005];//每个结点的度



int Find(int a)
{
    int r=a;
    while(father[a]!=a)
    {
        a=father[a];
    }
    father[r]=a;
    return a;
}

inline void Union(int a,int b)
{
    a=Find(a);
    b=Find(b);
    if(a!=b)
    {
        father[b]=a;
    }
}

int main()
{
    int ans;
    while(scanf("%d%d",&n,&m)==2)
    {
        ans=0;
        for(int i=1; i<=n; i++)
        {
            father[i]=i;
            //son[i]=0;
            deg[i]=0;
            son[i].init();
        }
        for(int i=0; i=2)
            {
                if(!son[i].odd_son_num)
                    ans+=1;
                else
                    ans=ans+son[i].odd_son_num/2;//在一个简单无向连通图中,至少要用n/2笔画画完所有边,n是奇点个数
            }
        }
        /*for(int i=1; i<=n; i++)
        {
            if(son[i].num>=2)
            {
               // printf("%d\n",son[i].num);
                set::iterator it;
                int cnt=0;
                for(it=son[i].st.begin(); it!=son[i].st.end(); it++)
                {
                    //printf("%d\n",*it);
                    if(deg[*it]%2)
                        cnt++;
                }
                if(!cnt)
                    ans+=1;
                else
                    ans=ans+cnt/2;//在一个简单无向连通图中,至少要用n/2笔画画完所有边,n是奇点个数
            }
        }*/
        printf("%d\n",ans);
    }
    return 0;
}


以上代码只是在计算每个连通分量要几笔画 的实现方法不同

你可能感兴趣的:(ACM)