有向图与无向图:欧拉路径&欧拉回路(一笔画)
咕了好久的图论的一小小小部分。
1、定义
欧拉路径 :不重复经过图上每一条边的路径
欧拉回路 : 起止点相同的欧拉路径
2、判定
∙ 有向图:
∙ 欧拉路径 :图中有且仅有 1 个点出度比入度多 1 ,为起点;图中有且仅有 1 个点入度比出度多 1 ,为终点;其余节点 入度 = 出度。
∙ 欧拉回路 :图中所有点 入度 = 出度,起止点为任意点。
∙ 无向图:
∙ 欧拉路径 :图中仅有 2 个点度数为奇数,其余点度数为偶数,这两个奇数点可以任意选为起点终点。
∙ 欧拉回路 :所有点度数都是偶数,起止点任意。
其实这些概念还是很好理解的,有进就有出,否则肯定有走不通的,回路就是起止点连在一起了。
3、寻找
假设我们已经选好起点,那么一次对图的 dfs 即可求出,我们只需要用栈记录即可。
注意!如果题中要求按字典序,那最好是用 vector 或者邻接矩阵。
附上例题:传送门~。
哦对了,无向图的最好是只用邻接矩阵,不然删边很麻烦的!!
例题代码,算是有向图欧拉路径的板子,一个通了别的也通了。
#include<cstdio> #include<queue> #include<iostream> #include<cstring> #include<algorithm> #include<cmath> #include<cctype> #include<vector> #include<string> #include<climits> #include<stack> using namespace std; template <typename T> inline void read(T &x){ x=0;char ch=getchar();bool f=0; while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();} while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); if(f)x=-x; } template <typename T,typename ...Args> inline void read(T &tmp,Args &...tmps){read(tmp);read(tmps...);} const int N = 1e6 + 5; int in[N],out[N],n,m,now[N]; vector<int>g[N]; stack<int>s; int flag = 1,cnt[2],st = 1; inline void dfs(int u){ for(int i=now[u];i<g[u].size();i=now[u]){ now[u] = i + 1;//避免重复走 dfs(g[u][i]); } s.push(u);//记录,也可以手写栈更快 } signed main(){ read(n,m); for(int i=1;i<=m;++i){ int u,v; read(u,v); g[u].push_back(v); in[v]++; out[u]++; //统计结点入度出度,如果是无向图统一一个数组记录度 } for(int i=1;i<=n;++i)sort(g[i].begin(),g[i].end());//题里要字典序,忽略啦~ for(int i=1;i<=n;++i){ if(in[i] != out[i])flag = 0; if(out[i] == in[i] + 1)cnt[1]++,st = i; if(in[i] == out[i] + 1)cnt[0]++; } if((!flag) && !(cnt[0] == cnt[1] && cnt[0] == 1))return printf("No"),0;//既没有回路也没有路径 dfs(st); while(!s.empty())printf("%d ",s.top()),s.pop();//输出 }
代码比较丑啦,但是精髓还在。
#include<cstdio> #include<stack> #include<cstring> #include<algorithm> #include<vector> #define rep(i,a,b) for(register int i=(a);i<=(b);++i) #define Rep(i,a,b) for(register int i=(a);i<(b);++i) #define rrep(i,a,b) for(register int i=(a);i>=b;--i) using namespace std; template <typename T> inline void read(T &x){ x=0;char ch=getchar();bool f=0; while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();} while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); if(f)x=-x; } template <typename T,typename ...Args> inline void read(T &tmp,Args &...tmps){read(tmp);read(tmps...);} const int N = 55; int g[N][N],t,n,du[N]; struct qwq{ int u,v; }; stack<qwq>s; int st; inline void init(){ while(!s.empty())s.pop(); memset(g,0,sizeof(g)); memset(du,0,sizeof(du)); } void dfs(int cur){ rep(i,1,50){ if(g[cur][i]){ g[cur][i]--,g[i][cur]--; dfs(i); s.push((qwq){cur,i}); } } } inline int solve(){ int ji = 0; rep(i,1,50){ ji += du[i]&1; } if(ji)return 0; dfs(st); return 1; } signed main(){ read(t); rep(i,1,t){ read(n); st = 0; rep(j,1,n){ int u,v; read(u,v); g[u][v]++,g[v][u]++; du[u]++,du[v]++; if(!st)st = u; } printf("Case #%d\n",i); if(!solve())puts("some beads may be lost"); else while(!s.empty())printf("%d %d\n",s.top().u,s.top().v),s.pop(); putchar('\n'); init(); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下