【基本概念】

  1. 欧拉通路:通过图中所有边一次且仅一次行遍所有顶点的通路
  2. 欧拉回路:通过图中所有边一次且仅一次行遍所有顶点的回路
  3. 欧拉图:具有欧拉回路的图
  4. 半欧拉图:具有欧拉通路而无欧拉回路的图
  5. 奇度点:与点相连的边的数目为奇数的点
  6. 偶度点:与点相连的边的数目为偶数的点

【欧拉通路/回路的判定】

1.无向图

1)欧拉通路:图是连通的,图中只有两个奇度点,分别是欧拉通路的两个端点

对于欧拉通路,除起点、终点外,每个点如果进入,显然一定要出去,因此都是偶点

2)欧拉回路:图是连通的,点均为偶度点

对于欧拉回路,每个点进入、出去的次数相等,因此没有奇点

2.有向图

1)欧拉通路:图是连通的,除两顶点外其余点的入度等于出度,且这两个顶点中,一个顶点入度比出度大1(起点),另一个入度比出度小1(终点)

2)欧拉回路:图是连通的,图中所有点的入度等于出度。

3.Fleury 算法

Fleury 算法是用于求无向图中欧拉回路的算法,其基本思想如下:

  1. 任取图 G 中一顶点 v0,令 P0=v0
  2. 假设沿 Pi=v0e1v1e2...eivi,走到顶点 vi,按下面的方法从 E(G)-{e1,e2,...,ei} 中选择 ei+1:
    1)ei+1 与 vi 相关联
    2)除非无别的边可供选择,否则 ei+1 不应是 Gi=G-{e1,e2,...,ei} 中的桥
  3. 当 2 不能再进行时,算法停止

可以证明的是,当算法停止时,所得到简单回路 Pm=v0e1v1e2...emvm(vm=v0) 为G中的欧拉回路

int n,m;
int start;//起点
int num;//奇度顶点个数
int degree[N];//顶点的度
int path[N];//存储欧拉回路
int cnt;//欧拉回路计数器
bool G[N][N];
stack<int> S;
void dfs(int x){S.push(x);for(int i=1;i<=n;i++){if(G[x][i]){G[x][i]=false;G[i][x]=false;dfs(i);break;}}
}
void Fleury(int x){S.push(x);while(!S.empty()){bool flag=false;for(int i=1;i<=n;i++){if(G[S.top()][i]==true){ //与起点有关联的边flag=true;break;}}if(flag==true){ //如果有关联的边int temp=S.top();S.pop();dfs(temp);}else{ //如果没有有关联的边path[cnt++]=S.top();S.pop();}}
}
int main(){scanf("%d%d",&n,&m);for(int i=1;i<=m;i++){int x,y;scanf("%d%d",&x,&y);G[x][y]=1;G[y][x]=1;degree[x]++;degree[y]++;}cnt=1;num=0;start=1;for(int i=1;i<=n;i++){if(degree[i]&1){//如果某点的度是奇数if(num==0)//记录起点start=i;num++;//奇度点个数+1}}if(num==0||num==2){//如果存在奇度顶点,则从奇度顶点出发,否则从顶点0出发Fleury(start);for(int i=cnt-1;i>=1;i--)printf("%d ",path[i]);printf("\n");}elseprintf("No Euler path.\n");return 0;
}

4.并查集判断无向图中是否存在欧拉回路

当给出一个无向图时,若要求判断图中是否存在欧拉回路,可以使用并查集判断图是否连通,并统计每个节点的度数,依次来判断是否存在。

若图连通且所有点的度数为偶数,则说明该无向图中存在欧拉回路。

#include<iostream>
#include<cstdio>
#include<cstring>
#define N 1001
using namespace std;
int n,m;
int degree[N];
int father[N];
int Find(int x){if(father[x]==-1)return x;return father[x]=Find(father[x]);
}
void Union(int x,int y){x=Find(x);y=Find(y);if(x!=y)father[x]=y;
}
int main(){while(scanf("%d%d",&n,&m)!=EOF){memset(degree,0,sizeof(degree));memset(father,-1,sizeof(father));for(int i=1;i<=m;i++){int x,y;scanf("%d%d",&x,&y);degree[x]++;degree[y]++;Union(x,y);}int cnt=0;//记录连通分量for(int i=1;i<=n;i++)if(Find(i)==i)cnt++;if(cnt!=1)//若cnt大于1,说明图不连通printf("NO\n");else{int num=0;//统计度数为奇数的点for(int i=1;i<=n;i++)if(degree[i]&1)num++;if(num==0)printf("YES\n");elseprintf("NO\n");}}return 0;
}

【应用】

对于一般的单词首尾相连的问题,通常都是转化为有向图的欧拉通路问题。

例如:给出多个单词,问能不能将所有单词组成一个序列,序列的前一个单词的尾字母与后一个单词的头字母相同

如果把每个单词看出无向的边,那么最终求出的欧拉通路可能存在两个单词尾部和尾部相连的情况。

1.无向欧拉图打印欧拉通路/回路

输入保证一个有 n 个点,m 条边的具有欧拉回路或欧拉路径的无向图,要求打印出图的欧拉回路或通路。

如果要打印欧拉通路,输入的 start 一定要是起点之一,即:,否则只是乱序打印图中所有的边。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<stack>
#define N 1001
using namespace std;
int n,m;
int G[N][N];
bool vis[N][N];//vis[i][j]=1表示点i到j之间存在一条边
void euler(int x){//打印以x为起点的欧拉回路或通路for(int y=1;y<=n;y++){if(vis[x][y]||vis[y][x]){vis[x][y]=0;//去掉x-y这条边vis[y][x]=0;//去掉y-x这条边euler(y);//首尾相连逆序打印欧拉通路//printf("%d %d\n",x,y);}}//逆序打印欧拉回路printf("%d ",x);
}
int main(){scanf("%d%d",&n,&m);for(int i=1;i<=m;i++){int x,y;scanf("%d%d",&x,&y);G[x][y]=1;G[y][x]=1;vis[x][y]=1;vis[y][x]=1;}int start;scanf("%d",&start);euler(start);//打印以x为起点的欧拉回路或通路return 0;
}

2.有向欧拉图打印欧拉通路/回路

输入保证是一 n 个点,m 条边的具有欧拉回路或欧拉路径的有向图,要求打印出图的欧拉回路或通路。

如果要打印欧拉通路,那么输入的 start 一定要是起点之一,即:,否则只是乱序打印图中所有的边。

1)邻接矩阵实现

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<stack>
#define N 1001
using namespace std;
int n,m;
int G[N][N];
bool vis[N][N];//vis[i][j]=1表示点i到j之间存在一条边
void euler(int x){//打印以x为起点的欧拉回路或通路for(int y=1;y<=n;y++){if(vis[x][y]){vis[x][y]=0;//去掉x-y这条边euler(y);//首尾相连逆序打印欧拉通路//printf("%d %d\n",x,y);}}//逆序打印欧拉回路printf("%d ",x);
}
int main(){scanf("%d%d",&n,&m);for(int i=1;i<=m;i++){int x,y;scanf("%d%d",&x,&y);G[x][y]=1;vis[x][y]=1;}int start;scanf("%d",&start);euler(start);//打印以x为起点的欧拉回路或通路return 0;
}

2)邻接链表实现

struct Edge{int endd;bool vis;Edge(int endd,bool vis):endd(endd),vis(vis){}
};
int n,m;
vector<Edge> G[N];
void euler(int x) {for(int i=G[x].size()-1; i>=0;i--) {if (!G[x][i].vis){G[x][i].vis = 1;euler(G[x][i].endd);}}printf("%d\n",x);
}int main() {scanf("%d%d",&n,&m);for(int i=1;i<=m;i++){int x,y;scanf("%d%d",&x,&y);G[x].push_back(Edge(y,false));G[y].push_back(Edge(x,false));}int start=1;euler(start);return 0;
}

图论 —— 图的遍历 —— 欧拉通路与欧拉回路问题相关推荐

  1. 图系列(四)欧拉通路与欧拉回路

    欧拉通路与欧拉回路 之前,写了图系列一二三,现在出四啦!这也意味着,对于图的部分,可以说50%以上常用的内容就已经过了一遍了.欧拉路的部分会稍微难一点,主要是我们要和定义打交道了.至于其他图的理论,我 ...

  2. 欧拉通路、欧拉回路、欧拉图和半欧拉图以及 Hierholzer 算法

    概念:欧拉通路(又称欧拉路径).欧拉回路.欧拉图和半欧拉图 定义 通过图中所有边恰好一次且行遍所有顶点的通路称为欧拉通路(又称欧拉路径). 通过图中所有边恰好一次且行遍所有顶点的回路称为欧拉回路. 具 ...

  3. 欧拉图——欧拉通路和欧拉回路

    定义: 欧拉通路 (欧拉迹):通过图中每条边且只通过一次,并且经过每一顶点的通路. 欧拉回路 (欧拉闭迹):通过图中每条边且只通过一次,并且经过每一顶点的回路. 欧拉图:存在欧拉回路的图. 简单说欧拉 ...

  4. 图论 —— 图的遍历

    [概述] 图的遍历问题是从图中某一顶点出发,系统地访问图中所有顶点,使每个顶点恰好被访问一次. 目前,图的遍历问题分为四类: 欧拉通路与欧拉回路问题:遍历完所有的边而不能有重复,即一笔画问题 中国邮递 ...

  5. ZOJ - 4122 Triangle City(最短路+欧拉通路+思维)

    题目链接:点击查看 题目大意:给出一张三角形的无向图,如下图所示 求出从点 ( 1 , 1 ) 到点 ( n , n ) 找到一条最长路,且每条边至多遍历一次,输出最长路的权值以及路径 题目分析:点 ...

  6. #1176 : 欧拉路·一(欧拉通路的判定)

    #1176 : 欧拉路·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho最近在玩一个解密类的游戏,他们需要控制角色在一片原始丛林里面探险,收集道具,并找 ...

  7. 欧拉回路 欧拉通路 欧拉回路图

    来源 一.定义 对于无向图: 1) 设G是连通无向图,则称经过G的每条边一次并且仅一次的路径为欧拉通路: 2) 如果欧拉通路是回路(起点和终点是同一个顶点),则称此回路为欧拉回路(Euler circ ...

  8. nysit 42 欧拉通路(一笔画图)

    题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=42 题目大意:给你一些点和边,问能否用一笔把这个图画出来,每条边只能画一次 思路:求是否存 ...

  9. POJ - 2513 Colored Sticks 欧拉通路+并查集+静态树

    一开始想用map来搞,但是感觉好复杂,然后想了一下看大佬们用trie做的,感觉十分合理就敲了一发. 一开始re,数组要开到550000 只会静态的字典树,在每个根节点看是否出现过改颜色,如果没有就把该 ...

最新文章

  1. mssql 数据库的备份与恢复
  2. SQL效率低下原因主要有
  3. oracle 兰贝斯_【咨询/顾问150-500人招聘_最新咨询/顾问150-500人招聘信息】-前程无忧...
  4. C#代码总结02---使用泛型来获取Asp前台页面全部控件,并进行属性修改
  5. Paging Structures in the Different Paging Modes
  6. 都有数据一直报空指针_C语言指针难吗?纸老虎而已,纯干货讲解(附代码)...
  7. 做游戏,学编程(C语言) 5 数组之生命游戏
  8. Windows 下安装 Redis 1
  9. 理解和使用NT驱动程序的执行上下文
  10. JS闭包文章--(翻译)Callbacks in Loops
  11. 6. JavaScript HTML DOM
  12. 整理C知识点--函数(重点)
  13. c语言累加和求平均数程序,c语言编程:连续输入若干个正整数,求其和及其平均值,直到输入0结束....
  14. C++ 编译报错discards qualifiers [-fpermissive]
  15. excel粘贴时出现故障_解决excel一复制就卡死的问题
  16. 苹果各版本手机更换电池的视频
  17. 11-小兔鲜项目搭建-代码
  18. 【论文阅读】KLD模型
  19. 【Cocos Creator 实战教程(4)】——黄金矿工(上)(节点动作、碰撞体相关)
  20. 2017西安网络赛B_Coin

热门文章

  1. 工信部发布《区块链 数据格式规范》标准(PPT全文)
  2. S5PV210裸机之GPIO
  3. python创建虚拟环境命令_python 创建虚拟环境
  4. 使用Java8改造出来的模板方法真的是yyds
  5. 漫画:互联网大佬都是这样聊天的
  6. 开发无框架单页面应用 — 老码农的祖传秘方
  7. MethodInvokingJobDetailFactoryBean的并发问题
  8. JEECG v3.0.beta发布,基于代码生成器的智能开发平台
  9. ORA-28000: the account is locked的解决办法
  10. 深入掌握JMS(二):一个JMS例子