欧拉回路的判定(Fleury算法)

定理:

(一)一个图有欧拉回路当且仅当它是连通的且每个顶点都有偶数度。

(二)一个图有欧拉通路当且经当它是连通的且除两个顶点外,其他顶点都有偶数度。

在第二个定理下,含奇数度的两个节点中,一个必为欧拉通路起点,另一个必为欧拉通路的终点。

设G是一个无向的欧拉图,求G中的一条欧拉回路的算法为:

(1)任意选取G中的一个点V0,令P0 = V0。

(2)假设沿pi = v0e1v1e2v2......eivi走到了点vi,按照下面的方法从E - {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中的一条欧拉回路。


欧拉回路的判定(Fleury算法)_第1张图片



#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <list>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#define PI acos(-1.0)
#define mem(a,b) memset(a,b,sizeof(a))
#define sca(a) scanf("%d",&a)
#define pri(a) printf("%d\n",a)
#define M 202
#define INF 100000001
using namespace std;
typedef long long ll;
struct stack
{
    int top,node[M];
}s;
int e[M][M],n;
void dfs(int x)
{
    int i;
    s.node[++s.top]=x;
    //cout<<s.top<<' '<<s.node[s.top]+1<<endl;
    for(i=0;i<n;i++)
    {
        if(e[i][x]>0)
        {
            e[i][x]=e[x][i]=0;  //删除这条边
            dfs(i);
            break;
        }
    }
}
void fleury(int x)
{
    int i,flag;
    s.top=0; s.node[s.top]=x;
    while(s.top>=0)
    {
        flag=0;
        for(i=0;i<n;i++)
        {
            if(e[s.node[s.top]][i]>0)
            {
                flag=1;
                break;
            }
        }
        if(!flag) printf("%d ",s.node[s.top--]+1);
        else dfs(s.node[s.top--]);
    }
    puts("");
}
int main( )
{
    int i,j,u,v,m,degree,num=0,start=0;
    scanf("%d%d",&n,&m);
    mem(e,0);
    for(i=0;i<m;i++)
    {
        scanf("%d%d",&u,&v);
        e[u-1][v-1]=e[v-1][u-1]=1;
    }
    for(i=0;i<n;i++)
    {
        degree=0;
        for(j=0;j<n;j++)
            degree+=e[i][j];
        if(degree&1)
        {
            start=i;
            num++;
        }
    }
    if(num==0||num==2) fleury(start);
    else printf("No Euler path\n");
    return 0;
}

#include <iostream>
#include <cstring>
#include <vector>

using namespace std;

const int MAX = 10240;

int N, M, pCnt[MAX];
int pMap[MAX][MAX];
vector<int> pVec;

void Search(int x);
void Euler_Circuit();

int main()
{
	cin >> N >> M;
	memset(pMap, 0, sizeof(pMap));
	for(int i = 1; i <= M; i++)
	{
		int s, e;
		cin >> s >> e;
		pMap[s][e] = pMap[e][s] = 1;	// 无向图
	}
	Euler_Circuit();
	return 0;
}

void Euler_Circuit()
{
	int nStart = 1, nOddNum = 0;	// nStart保存起点,nOddNum保存有几个顶点有奇数度
	memset(pCnt, 0, sizeof(pCnt));
	for(int i = 1; i <= N; i++)
	{
		for(int j = 1; j <= N; j++)
		{
			pCnt[i] += pMap[i][j];		// 计算各个顶点的度
		}
	}

	for(int i = 1; i <= N; i++)	// 统计奇数度顶点的个数
	{
		if(pCnt[i] & 1)
		{
			nStart = i;
			nOddNum++;
		}
	}
	if(nOddNum > 2 || nOddNum == 1)		// 不存在欧拉回路
	{
		cout << "Not Exsit Euler Circuit" << endl;
	}
	else
	{
		Search(nStart);
		for(int i = 0; i < pVec.size(); i++)
		{ cout << pVec[i] << " "; }
		cout << endl;
	}
}

void Search(int x)
{
	for(int i = 1; i <= N; i++)
	{
		if(pMap[x][i] == 1)
		{
			pMap[x][i] = pMap[i][x] = 0;	// 删边
			Search(i);	
		}
	}
	pVec.push_back(x);
}


你可能感兴趣的:(图论,欧拉回路)