欧拉回路

欧拉回路笔记

无向图

要求是每个点的入度是偶数,另外如果有两个奇数点,是欧拉道路。

有向图

记出度为 \(1\) ,入度和 \(-1\) ,如果所有和为 \(0\) ,是欧拉回路。有一个 \(1\) 和 一个 \(-1\) ,是欧拉路径。一个

关于这道题

这道题要区分无向图的方向,所以我们将边的 id 分正负存储,标记只标记绝对值。其他的就只是一个欧拉道路的大杂烩罢了。

code

#include <bits/stdc++.h>
#define int long long
using namespace std;
constexpr int maxn = 2e5+10;
void read(int &);

typedef struct node
{
    int v,id;
    node(int x,int y):v(x),id(y) {}
}node;

vector<node> gra[maxn];
int go[maxn];// 存储当前点可以访问的边
int rd[maxn];
bool vis[maxn];
int ans[maxn];

void dfs1(int u)
{
    for(int &i=go[u];i<(int)gra[u].size();)
    {
        if(vis[llabs(gra[u][i].id)]) // 跳过被用过的无向边
        {
            ++i;
            continue;
        }
        vis[llabs(gra[u][i].id)]=1;// 标记
        int id=gra[u][i].id;       // 存储当前边
        dfs1(gra[u][i++].v);
        ans[++ans[0]]=id;
    }
}

void solve1()
{
    int n,m;
    read(n);
    read(m);
    int u=0,v=0;
    for(int i=1;i<=m;++i)
    {
        read(u);
        read(v);
        gra[u].emplace_back(node(v,i));
        gra[v].emplace_back(node(u,-i));
        rd[u]^=1;
        rd[v]^=1;
    }
    for(int i=1;i<=n;++i)
    {
        if(rd[i])// 奇数
        {
            printf("NO\n");
            return;
        }
    }
    dfs1(u);
    if(ans[0]!=m) // 不连通
    {
        printf("NO\n");
        return;
    }
    printf("YES\n");
    for(int i=ans[0];i>0;--i)
    {
        printf("%lld ",ans[i]);
    }
}

void dfs2(int u)
{
    for(int &i=go[u];i<(int)gra[u].size();)
    {
        int id=gra[u][i].id;// 正常的当前弧优化
        dfs2(gra[u][i++].v);
        ans[++ans[0]]=id;
    }
}

void solve2()
{
    int n,m;
    read(n);
    read(m);
    int u=0,v=0;
    for(int i=1;i<=m;++i)
    {
        read(u);
        read(v);
        gra[u].emplace_back(node(v,i));
        --rd[u];
        ++rd[v];
    }
    for(int i=1;i<=n;++i)
    {
        if(rd[i])
        {
            printf("NO\n"); 
            return;
        }
    }
    dfs2(u);
    if(ans[0]!=m)
    {
        printf("NO\n");// 不联通
        return;
    }
    printf("YES\n");
    for(int i=ans[0];i>0;--i)
    {
        printf("%lld ",ans[i]);
    }
}

signed main()
{
    #ifndef ONLINE_JUDGE
    freopen("cjdl.in","r",stdin);
    freopen("cjdl.out","w",stdout);
    #endif // ONLINE_JUDGE

    int op;
    read(op);
    if(op==1)
    {
        solve1();
    }
    else
    {
        solve2();
    }

    return 0;
}

void read(int &x)
{
    x=0;
    int f=1;
    signed c=getchar();
    while(!isdigit(c))
    {
        if(c=='-')
        {
            f=-1;
        }
        c=getchar();
    }
    while(isdigit(c))
    {
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    x*=f;
}
posted @ 2025-11-25 13:12  玖玮  阅读(6)  评论(0)    收藏  举报