定义:
欧拉路径:指图中的一条路径,使得所有边都被经过且只经过一次
欧拉回路:指图中的一条欧拉路径,且起点和终点相同。
欧拉图:指有欧拉回路的图
半欧拉图:指有欧拉路径但没有欧拉回路的图
性质:
1.如果一个无向图是欧拉图,那么所有节点的度数均为偶数
2.如果一个无向图是半欧拉图,那么除了两个节点的度数为奇数,其他的节点度数都为偶数
3.如果一个有向图是欧拉图,那么对于每个节点,它的入度和出度相等。
4.如果一个有向图是半欧拉图,那么除了两个节点的入出度差为 \(1\) 以外,其他节点入出度差都为 \(0\)(即相等)。
HierHolzer:
problem:
给定图 \(G\),求 \(G\) 中字典序最小的欧拉路径
solution:
先考虑生成欧拉路径:
1.找到出度减入度为 \(1\) 的节点(假如没有默认为 1 号节点),将其作为起始节点进行 \(dfs\)。
2.考虑 \(u\) 节点未访问过的边 \((u,v)\),如果没有,将 \(u\) 节点压入栈并返回。
3.标记 \((u,v)\) 为已访问。
4.对 \(v\) 进行2,3操作。
5.所有操作完成后,将栈中元素输出。
通过这里我们知道,元素是倒序输出的,所以我们要让后面的元素尽量小,所以其实就是要将链式前向星中的元素从大到小排序。
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
struct edge{
int v,next;
}edges[N*2];
int head[N],idx;
int n,m;
void add_edge(int u,int v){
idx++;
edges[idx].v=v;
edges[idx].next=head[u];
head[u]=idx;
return;
}
int stk[N*3],top;
void dfs(int u){
for(int i=head[u];i;i=head[u]){
int v=edges[i].v;
head[u]=edges[i].next;
dfs(v);
}
stk[++top]=u;
return;
}
int degin[N],degout[N];
struct stu{
int u,v;
}st[N*2];
bool cmp(struct stu st1,struct stu st2){
if(st1.u==st2.u)return st1.v>st2.v;
return st1.u>st2.u;
}
signed main(){
std::ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>st[i].u>>st[i].v;
}
sort(st+1,st+m+1,cmp);
for(int i=1;i<=m;i++){
add_edge(st[i].u,st[i].v);
degin[st[i].v]++;
degout[st[i].u]++;
}
int s=1,cnt=0;
for(int i=1;i<=n;i++){
if(abs(degin[i]-degout[i])&1)cnt++;
if(degout[i]-degin[i]==1)s=i;
}
if(cnt!=2&&cnt!=0){
cout<<"No"<<endl;
return 0;
}
dfs(s);
while(top>0){
cout<<stk[top]<<" ";
top--;
}
return 0;
}
标签:head,int,路径,edges,&&,回路,节点,欧拉
From: https://www.cnblogs.com/little-corn/p/18157440