HDU3018Ant Trip(欧拉回路)

题目地址

解题报告:

欧拉回路:图G,若存在一条路,经过G中每条边有且仅有一次,称这条路为欧拉路,如果存在一条回路经过G每条边有且仅有一次,

称这条回路为欧拉回路。具有欧拉回路的图成为欧拉图。

判断欧拉路是否存在的方法

有向图:图连通,有一个顶点出度大入度1,有一个顶点入度大出度1,其余都是出度=入度。

无向图:图连通,只有两个顶点是奇数度,其余都是偶数度的。

判断欧拉回路是否存在的方法

有向图:图连通,所有的顶点出度=入度。

无向图:图连通,所有顶点都是偶数度。

本题呢。先用并查集查看共有几棵树, 记录下每棵树中度为奇数的点的个数。 如果该树中度为奇数的点的个数为0, 且代表元的度为0,证明该点为孤立的点,按题目要求的略过就可以了。如果代表元的度不为0, 且该树中度为奇数的店为0,那么证明为欧拉回路,1组就能搞定;如果这两种情况都不属于,那么浏览该树中的点要用奇数点的个数/2

代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXN 100005

//degree为度,p为并查集,cnt为记录该树中度为奇数的点的个数
int degree[MAXN], p[MAXN], cnt[MAXN], hash[MAXN], q[MAXN];

int find(int x){return p[x] == x ? x : (p[x]=find(p[x]));}

void Union(int u, int v){
    int x = find(u), y = find(v);
    if(x != y){
        p[x] = y;
    }
}

int main(){

    int n, m, i, a, b, top;
    while(scanf("%d %d", &n, &m) == 2){
        top = 0;
        for(i=1; i<=n; i++){
            cnt[i] = degree[i] = hash[i] = 0;
            p[i] = i;
        }

        for(i=1; i<=m; i++){
            scanf("%d %d", &a, &b);
            Union(a, b);
            degree[a]++;
            degree[b]++;
        }

        for(i=1; i<=n; i++){
            int k = find(i);    //查找代表元
            if(!hash[k]){   //如果该代表元没有被访问过
                q[top++] = k;   //将该代表元存起来
                hash[k]=1;
            }
            if(degree[i] % 2) cnt[k]++;
        }

        int sum = 0;
        for(i=0; i<top; i++){
            int k = q[i];
            if(degree[k] == 0) continue;    //孤立的点

            if(cnt[k] == 0) sum++;  //欧拉回路
            else sum += (cnt[k] / 2);   
        }

        printf("%d\n", sum);
    }

    return 0;
}
原文地址:https://www.cnblogs.com/tanhehe/p/2922904.html