Fleury算法模板

1. Fleury(佛罗莱)算法
设G为一无向欧拉图,求G中一条欧拉回路的算法为:
1)  任取G中一顶点v0,令P0 = v0;
2)  假设沿Pi = v0e1v1e2v2 …eivi走到顶点vi,按下面方法从E(G)- { e1, e2, …, ei}中选ei+1:

a)  ei+1与vi相关联;
b)  除非无别的边可供选择,否则ei+1不应该是Gi = G - { e1, e2, …, ei}中的桥。


3)  当2)不能再进行时算法停止。
可以证明的是,当算法停止时,所得到的简单回路Pm= v0e1v1e2v2 …emvm, (vm= v0)为G中一条欧拉回路。

 


    设无向图G(V, E)为连通图,若边集E1⊆E,在图G中删除E1中所有的边后得到的子图是不连通的,而删除了E1的任一真子集后得到的子图是连通图,则称E1是G的一个割边集。若一条边构成一个割边集,则称该边为割边,或桥 。

例如,如下图G所示的无向连通图,边(1, 5)、(4, 6)、(8, 10)和(8, 9)都是图G中的桥。

 

 

题目描述:用Fleury算法输出下图(a)中的欧拉回路。

输入描述:

    假设数据输入时采用如下的格式进行输入:首先输入顶点个数n和边数m,然后输入每条边,每条边的数据占一行,格式为:u v,表示从顶点u到顶点v的一条有向边。

输出描述:
    在下面的代码中,首先判断是否存在欧拉回路或通路,如果存在则选择一个正确的顶点按照Fleury算法输出欧拉回路或通路。

#include <iostream>
#include <cstring>

using namespace std;

const int MAXN = 200;

struct Stack
{
	int top;
	int node[MAXN];
}s;//顶点的栈结构

int Edge[MAXN][MAXN];//储存图的邻接矩阵
int n;//顶点个数

void DFS( int x )//从x开始搜索,直到无法进行下去时,搜索结束
{
	s.top++;
	s.node[ s.top ] = x;
	int i;
	for(i = 0; i < n; ++i)
	{
		if(Edge[x][i] > 0)//每走一步就要删除该边
		{
			Edge[x][i]  = Edge[i][x] = 0;
			DFS( i );
			break;
		}
	}
	return;
}

void Fleury( int start )
{
	int i;
	s.top = 0;
	s.node[ s.top ] = start;
	while( s.top >= 0 )
	{
		int b = 0;
		for(i = 0; i < n; ++i)
		{
			if(Edge[ s.node[s.top] ][i] > 0)
			{
				b = 1;
				break;
			}
		}
		if(b == 0)//如果b = 0说明,Edge[s.node[ s.top-1 ] ][ s.node[ s.top ] ]是桥,
		{          //而该栈顶元素一定会由次栈顶元素s.node[s.top-1]经过该桥到达,s.node[ s.top ]也无法继续拓展下去,可以直接输出
			cout<<s.node[ s.top ] + 1<<" ";
			s.top--;
		}
		else
		{
			s.top--;
			DFS( s.node[s.top + 1] );//如果有,那就继续拓展下去
		}
	}
	cout<<endl;
}



int main()
{
	int i, j;
	int m, s, t; //边数,读入的边的起点和终点
	int degree, num, start;//每个顶点的度、奇度顶点个数、欧拉回路的起点
	cin>>n>>m;//n顶点数、m边数
	memset( Edge, 0, sizeof(Edge) );
	for(i = 0; i < m; ++i)
	{
		cin>>s>>t;
		Edge[ s-1 ][ t-1 ] = Edge[ t-1 ][ s-1 ] = 1;
	}
	//如果存在奇度顶点,则从奇度顶点出发,否则从顶点0出发
	num = start = 0;
	for(i = 0; i < n; ++i)//判断是否存在欧拉回路
	{
		degree = 0;
		for(j = 0; j < n; ++j)
			degree += Edge[i][j];
		if(degree % 2 == 1)
		{
			num++;
			start= i;
		}
	}
	if(num == 0 || num == 2)
		Fleury( start );
	else
		cout<<"No Euler path"<<endl;
	return 0;
}


/**

9 14
1 2
1 8
2 3
2 8
2 9
3 4
4 5
4 6
4 9
5 6
6 7
6 9
7 8
8 9

*/


 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值