背景介绍
1) 欧拉图:存在经过图中每条边恰好一次并且仅一次行遍所有点的回路
- 通俗来说,该回路有两个特点:
- 边:包括图中所有边(不重复地)
- 点:包括图中所有点(可重复地)
2) 欧拉图判断:不存在奇度顶点
- 通俗来说,图中每个顶点与偶数条边相连
3) 欧拉回路求解:判断一个图是欧拉图,下一步就会问这条回路具体是什么,Fleury算法就是用来找出无向欧拉图可能的的欧拉回路
4) Fleury算法
- 任意选择图中的一个顶点作为初始顶点a1
- 优先选择走非桥(删除该边后不会连通分支不会增加,逼不得已再走桥。按照与该点连接边数判断:
2.1 a1与某个点有两条边相连=>这两条边必为非桥
2.2 a1与某个点仅一条边相连:皆有可能(是否可能存在a1分别与a2、a3仅有一条边,边(a1,a2)为桥,而(a1,a3)非桥???) - 若是未走完所有边,继续第二步
5)实现代码C++
#include<iostream>
using namespace std;
//该算法适用于无向欧拉图找出具体的欧拉通路
int main()
{
int n;
cout<<"please input the order of metrix: ";
cin>>n;
int a[n+1][n+1];
for(int i=1;i<=n;i++)//使用邻接矩阵表示图
{
for(int j=1;j<=n;j++)
{
cin>>a[i][j];
}
}
int start=1,present=start,tmp=0;
//算法思想:能不走桥就不走桥
while(true)
{
int flag2=0,flag1=0;
for(int j=1;j<=n;j++)//遍历该点与其它所有点的邻接关系
{
if(a[present][j]>=2)//找到第一条非桥,就走它
{
flag2++;//记录是否存在非桥
a[present][j]--;//边是二元关系,两个点都要改变;包括了环的情况
a[j][present]--;
cout<<"("<<present<<","<<j<<")"<<" ";//模拟走的道路
present=j;//更新当前点
break;//找到就进入下一个点
}
if(a[present][j]==1&&flag1==0)//记录第一个与当前点存在一条边(不一定是割边)的点
{
flag1++;
tmp=j;
}
}
if(flag2==0&&flag1==1)//只能走桥
{
a[present][tmp]--;
a[tmp][present]--;
cout<<"("<<present<<","<<tmp<<")"<<" ";
present=tmp;
}
if(flag2==0&&flag1==0)break;//当矩阵为零矩阵时结束
}
return 0;
}
6)测试用例
2(图有两个点,对应矩阵的阶为2)
0 2
2 0
3
0 2 2
2 0 2
2 2 0
3
0 2 0
2 0 2
0 2 0
3
0 0 2
0 0 2
2 2 0
4 (第一个点有一个环)
2 0 1 1
0 0 1 1
1 1 0 0
1 1 0 0
收获
- 使用矩阵这个强大的工具表示图,对图的操作,如增删边,找回路等都可以有矩阵相应计算完成
- 把思路理清楚后再用代码实现,编程时注意标记重置的位置