Hdu 3018 Ant Trip

欧拉回路



给出一个图,需要几笔能画完题目所描述的所有边。

如果是欧拉图,就一笔画完;如果存在其他连通分支,则笔画数 = 奇度数 / 2 。用并查集求出有几个连通分支,用ans数组保存连通分支。

通过判断度数是奇偶数来判断是否为欧拉图,笔画数 = 奇度数 / 2 + 回路数。




AC代码:

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

#define MAXN 100010

using namespace std;

int p[MAXN];
int deg[MAXN];
int v[MAXN];
bool vis[MAXN];
int ans[MAXN];

void Init(int n) {
    for(int i = 1; i <= n; i++) {
        p[i] = -1;
        deg[i] = 0;
        v[i] = 0;
        vis[i] = false;
    }
}

int Find(int x) {
    if(p[x] >= 0) {
        p[x] = Find(p[x]);
        return p[x];
    }
    return x;
}

void Union(int R1, int R2) {
    int r1 = Find(R1);
    int r2 = Find(R2);
    int sum = p[r1] + p[r2];
    if(r1 == r2)
        return ;
    if(p[r1] < p[r2]) {
        p[r1] = r2;
        p[r2] = sum;
    }
    else {
        p[r2] = r1;
        p[r1] = sum;
    }
}

int main() {
    int n, m;
    while(scanf("%d%d", &n, &m)!=EOF) {
        Init(n);
        for(int i = 1; i <= m; i++) {
            int a, b;
            scanf("%d%d", &a, &b);
            deg[a]++;
            deg[b]++;
            Union(a, b);
        }
        int cnt = 0;
        for(int i = 1; i <= n; i++) {
            int f = Find(i);
            if(!vis[f]) {
                vis[f] = true;
                ans[cnt++] = f;
            }
            if(deg[i]%2 == 1) {
                v[f]++;
            }
        }
        int ret = 0;
        for(int i = 0; i < cnt; i++) {
            if(deg[ans[i]] == 0)
                continue;
            if(v[ans[i]] == 0)
                ret++;
            else
                ret += v[ans[i]]/2;
        }
        printf("%d\n", ret);
    }
    return 0;
}


你可能感兴趣的:(Hdu 3018 Ant Trip)