一本通1527:【例 1】欧拉回路

该篇文章展示了如何使用C++编写EulerCircuit模板类,用于检测给定图(有向或无向)中是否存在环路,以及输出环路的顺序。代码片段包括输入输出流处理和图的边的添加操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include <cctype>
#include <cstdio>
namespace io {
using namespace std;
#define fastcall __attribute__((optimize("-O3")))
#define IL __inline__ __attribute__((always_inline))
struct istream {
#define M (1 << 25)
    int f;
    char buf[M], *ch = buf - 1;
    fastcall IL istream() {
        fread(buf, 1, M, stdin);
    }
    fastcall IL istream &operator>>(int &x) {
        f = 1;

        while (!isdigit(*++ch))
            if (*ch == '-')
                f = -1;

        for (x = *ch & 15; isdigit(*++ch);)
            x = x * 10 + (*ch & 15);

        x *= f;
        return *this;
    }
    fastcall IL istream &operator>>(long long &x) {
        f = 1;

        while (!isdigit(*++ch))
            if (*ch == '-')
                f = -1;

        for (x = *ch & 15; isdigit(*++ch);)
            x = x * 10 + (*ch & 15);

        x *= f;
        return *this;
    }
    fastcall IL istream &operator>>(char &c) {
        c = *++ch;
        return *this;
    }
#undef M
} cin;
struct ostream {
#define M (1 << 23)
    char buf[M], *ch = buf - 1;
#define endl (char)10
    fastcall IL ostream &operator<<(int x) {
        if (!x) {
            *++ch = '0';
            return *this;
        }

        if (x < 0) {
            x = -x;
            *++ch = '-';
        }

        static int S[20], *top;
        top = S;

        while (x) {
            *++top = x % 10 ^ 48;
            x /= 10;
        }

        for (; top != S; --top)
            *++ch = *top;

        return *this;
    }
    fastcall IL ostream &operator<<(long long x) {
        if (!x) {
            *++ch = '0';
            return *this;
        }

        if (x < 0) {
            x = -x;
            *++ch = '-';
        }

        static int S[20], *top;
        top = S;

        while (x) {
            *++top = x % 10 ^ 48;
            x /= 10;
        }

        for (; top != S; --top)
            *++ch = *top;

        return *this;
    }
    fastcall IL ostream &operator<<(const char &x) {
        *++ch = x;
        return *this;
    }
    fastcall IL ~ostream() {
        fwrite(buf, 1, ch - buf + 1, stdout);
    }
#undef M
} cout;
}  // namespace io
using namespace io;

#include <cstring>
#include <queue>
namespace eulercircuit {
using namespace std;
#define fastcall __attribute__((optimize("-O3")))
#define IL __inline__ __attribute__((always_inline))
template <int maxn>
class EulerCircuit {
public:
    EulerCircuit(void) {
        init();
    }
    fastcall IL void init(const int &n = 0, const bool &f = false) {
        this->n = n;
        directed = f;
        memset(G, 0, sizeof(G));
        memset(head, 0, sizeof(head));
        cnt = 0;
        return;
    }
    fastcall IL void AddEdge(const int &u, const int &v) {
        G[++cnt].to = v;
        G[cnt].nxt = head[u];
        head[u] = cnt;
        deg[0][u]++, deg[1][v]++;
        f[u] = f[v] = true;
        return;
    }
    int ans[maxn], c;
    fastcall IL bool eulercircuit(void) {
        if (directed) {
            for (int i = 1; i <= n; i++)
                if (deg[0][i] != deg[1][i])
                    return false;
        } else {
            for (int i = 1; i <= n; i++)
                if ((deg[0][i] & 1) || (deg[1][i] & 1))
                    return false;
        }

        tot = c = 0;

        for (int i = 1; i <= n; i++)
            if (f[i]) {
                stack[++tot] = i;
                break;
            }

        bool flag;
        int v = !directed, val = 0;

        while (tot) {
            flag = false;

            for (int i = head[stack[tot]]; i; i = G[i].nxt)
                if (!vis[((i - 1) >> v) + 1]) {
                    val++;
                    head[stack[tot]] = G[i].nxt;
                    flag = true;
                    vis[((i - 1) >> v) + 1] = 1;
                    stack[++tot] = G[i].to;
                    tmp[tot] = i;

                    if (v) {
                        tmp[tot] = ((i - 1) >> 1) + 1;

                        if (!(i & 1))
                            tmp[tot] = 1 + ~tmp[tot];
                    }

                    break;
                }

            if (!flag) {
                if (tot != 1)
                    ans[++c] = tmp[tot];

                tot--;
            }
        }

        for (int p = 1; (p << 1) <= c; p++)
            ans[p] ^= ans[c - p + 1] ^= ans[p] ^= ans[c - p + 1];

        return val == cnt >> v;
    }
    struct edge {
        int to, nxt;
    };
    edge G[maxn];
    int head[maxn], cnt;
    bool directed;
    int n;

private:
    bool vis[maxn], f[maxn];
    int stack[maxn], tot;
    int deg[2][maxn];
    int tmp[maxn];
};
}  // namespace eulercircuit
using namespace eulercircuit;

EulerCircuit<400010> s;

int main() {
    int t, n, m;
    cin >> t >> n >> m;

    if (!m) {
        cout << 'Y' << 'E' << 'S' << endl;
        return 0;
    }

    s.init(n, !(t & 1));
    int u, v;

    while (m--) {
        cin >> u >> v;
        s.AddEdge(u, v);

        if (t & 1)
            s.AddEdge(v, u);
    }

    if (s.eulercircuit()) {
        cout << 'Y' << 'E' << 'S' << endl;

        for (int i = 1; i < s.c; i++)
            cout << s.ans[i] << ' ';

        cout << s.ans[s.c] << endl;
    } else
        cout << 'N' << 'O' << endl;

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值