欧拉回路
欧拉回路笔记
无向图
要求是每个点的入度是偶数,另外如果有两个奇数点,是欧拉道路。
有向图
记出度为 \(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;
}

浙公网安备 33010602011771号