欧拉路径和欧拉回路
- 格式:ppt
- 大小:150.50 KB
- 文档页数:40


欧拉发现的数学结论欧拉(Leonhard Euler)是一位杰出的数学家,他在数学领域取得了许多重大成就。
以下是一些重要的数学结论:1. 欧拉公式(Euler's Formula):欧拉公式是复数领域的一个重要公式,它将复指数与三角函数联系起来。
欧拉公式如下:e^(ix) = cos(x) + i*sin(x)2. 欧拉恒等式(Euler's Identity):欧拉恒等式是数学领域的一个著名等式,它将欧拉公式与阶乘联系起来:e^(iπ) + 1 = 03. 欧拉-费马定理(Euler-Fermat Theorem):欧拉和费马共同证明了这个定理,它关于复数域上的代数方程的解的个数:如果a、b、c 是互质的整数,且方程x^n + ax^(n-1) + bx^(n-2) + ... + c = 0 有解,那么解的个数不超过n+1。
4. 欧拉多边形(Euler Polygon):欧拉在图论中提出了欧拉多边形的概念,它是一个简单多边形,其顶点数、边数和面数满足以下关系:V - E + F = 2其中,V 表示顶点数,E 表示边数,F 表示面数。
5. 欧拉回路(Euler Circuit):在图论中,欧拉回路是指在一个图中,经过每条边一次且仅一次,最后回到起点的一条路径。
欧拉回路的存在性及其性质是图论研究的重要内容。
6. 欧拉-伯努利定理(Euler-Bernoulli Theorem):欧拉在力学领域提出了欧拉-伯努利定理,它关于悬链线的形状:在给定两端固定且无弹簧常数的悬链线上,任意一点的曲率半径与该点的张力成正比。
这些仅是欧拉发现的众多数学结论的一部分。
他在数学、物理、力学、天文学等领域做出了巨大贡献,影响了后世数学家和其他科学家的工作。
欧拉路径貌似很多博客都喜欢⽤⼀笔画来引⼊欧拉路径,但像您这样的强者时⽆需那些繁琐的东西,我们直接进⼊正题。
定义:图中经过所有边恰好⼀次的路径叫做欧拉路径。
如果起点和终点⼀样,那它就是欧拉回路。
判定:判定当前图中是否存在欧拉路径其实⽐寻找更⿇烦显然,欧拉回路也是欧拉路径,但为了⽅便区分,下⽂判定中的欧拉路径特指起点和终点不同。
判定⽅法:⾸先,当且仅当这张图将有向边视为⽆向边时联通。
1. 有向图欧拉路径:图中恰好存在⼀个点(起点)出度⽐⼊度多1,恰好⼀个点(终点)⼊度⽐出度多1,剩下所有点⼊度等于出度。
2. 有向图欧拉回路:图中所有点⼊度等于出度(任⼀点都可以做起点和终点)。
3. ⽆向图欧拉路径:图中恰好有两个点的度数为奇数(起点和终点),其他所有点的度数为偶数。
4. ⽆向图欧拉回路:图中所有点的度数都为偶数(任⼀点都可以做起点和终点)。
寻找:算法⼀:Fluery 算法。
时间复杂度O(m2),不常⽤。
算法⼆:Hierholzer 算法。
时间复杂度O(m),常⽤。
只写 Hierholzer 算法,做法⾮常简单。
1. 从起点开始dfs,标记选了的边不能重复选,这⾥⽤类似Dinic的当前弧优化。
2. 当前点不存在出边时回退,并将当前点⼊栈P。
3. 当dfs结束时倒序输出栈P中的节点即可。
算法导论上似乎有该算法证明。
例题:题⽬保证联通,所以直接判断⼊度和出度即可。
要求字典序最⼩,那么每次都要选能到达的最⼩的点。
可以将边离线下来按v从⼤到⼩排序,然后依次插⼊到链式前向星⾥,这样可以保证每次选到的都是最⼩的。
当前弧优化不加复杂度就假了。
code:#include<bits/stdc++.h>using namespace std;#define int long long#define in read()inline int read(){int p=0,f=1;char c=getchar();while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9'){p=p*10+c-'0';c=getchar();}return p*f;}const int N=1e5+5;const int M=2e5+5;int n,m;struct edge{int v,nxt;}e[M];inline void insert(int u,int v){e[++en].v=v;e[en].nxt=head[u];head[u]=en;}struct QWQ{int u,v;}E[M];inline bool cmp(QWQ a,QWQ b){return a.v>b.v;}int p[M],pn;void dfs(int u){for(int i=head[u];i;i=head[u]){int v=e[i].v;head[u]=e[i].nxt;dfs(v);}p[++pn]=u;}int flagin,flagout,flag;int ind[N],outd[N];int S=1;signed main(){n=in,m=in;for(int i=1;i<=m;i++)E[i].u=in,E[i].v=in,outd[E[i].u]++,ind[E[i].v]++;sort(E+1,E+1+m,cmp);for(int i=1;i<=m;i++)insert(E[i].u,E[i].v);for(int i=1;i<=n;i++){if(ind[i]!=outd[i])flag++;if(ind[i]==outd[i]+1)flagout++;if(ind[i]+1==outd[i])flagin++,S=i;}if(flag==0||(flag==2&&flagout==1&&flagin==1)){dfs(S);for(int i=pn;i>=1;i--)cout<<p[i]<<' ';}else cout<<"No";return 0;}练习:将每个字母视为点,单词视为边,就和上⾯差不多了,注意欧拉路径的起始点。