Fleury算法 -求无向欧拉图的欧拉回路


背景介绍

1) 欧拉图:存在经过图中每条边恰好一次并且仅一次行遍所有点的回路

  • 通俗来说,该回路有两个特点:
    • 边:包括图中所有边(不重复地)
    • 点:包括图中所有点(可重复地)

2) 欧拉图判断:不存在奇度顶点

  • 通俗来说,图中每个顶点与偶数条边相连

3) 欧拉回路求解:判断一个图是欧拉图,下一步就会问这条回路具体是什么,Fleury算法就是用来找出无向欧拉图可能的的欧拉回路

4) Fleury算法

  1. 任意选择图中的一个顶点作为初始顶点a1
  2. 优先选择走非桥(删除该边后不会连通分支不会增加,逼不得已再走桥。按照与该点连接边数判断:
    2.1 a1与某个点有两条边相连=>这两条边必为非桥
    2.2 a1与某个点仅一条边相连:皆有可能(是否可能存在a1分别与a2、a3仅有一条边,边(a1,a2)为桥,而(a1,a3)非桥???)
  3. 若是未走完所有边,继续第二步

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


收获

  • 使用矩阵这个强大的工具表示图,对图的操作,如增删边,找回路等都可以有矩阵相应计算完成
  • 把思路理清楚后再用代码实现,编程时注意标记重置的位置

  • 8
    点赞
  • 79
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值