欧拉回路&&欧拉路径输出模版

知识点:
(1)欧拉路径定义:从一个点出发,不重不漏的经过图中每一条边的一条路径(允许多次经过同一个点)。
(2)欧拉路径的判断:
···········<1>若为无向图,则需连通,且图中恰好存在两个点的度数是奇数,其他节点的度数为偶数,这两个度数为奇数的点就是起点与终点;或者所有点度数都是偶数。
···········<2>若为有向图,则需连通,且图中恰好存在一个点入度比出度多一,一个点出度比入度多一,其他节点的出度等于入度;或者所有点入度等于出度。

(3)欧拉回路定义:起点和终点是一个点的欧拉路径。

(4)欧拉回路的判断:
············<1>若为无向图,则需连通,且所有点的度数都是偶数。
············<2>若为有向图,则需连通,且所有点的入度等于出度。

(5)通俗解释:欧拉路径就是一笔画,欧拉回路是特殊的一笔画:起点和重点重合的一笔画。

代码实现:Hierholzer算法
(1)首先我们要确定出起点,然后从起点开始不走重复边的递归。
(2)对于每一个点,当访问完所有的边时,把这个点加入答案序列。
(3)最后,输出答案序列即为一条欧拉路径依次经过的点

伪代码

void dfs(int u){
	for(){ //遍历所有与u相邻的点v 
		if(!vis[v]){   //u与v的这条边没被访问过 
			vis[v]=1;    
			dfs(v);  //递归与u相邻的点v 
		}
	}
	s.push(u); //没有边了,将u进入序列 
}

but这里出现了一个问题:
这样写时间复杂度是不对的。按照算法,我们不能走重复边,但如果每次都vis判断一遍,则会出现很多次访问同一条边,时间复杂度是不正确的。

处理:
对于任意一个点 u 来说,建完图之后访问边是有顺序的,我们新开一个数组 delete delete 记录访问到哪个位置即可(即该删除哪个位置)。

是否存在欧拉路径&&欧拉回路只要按照上文给出的判定方法实现就可以了

上代码

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int ru[N],chu[N],n,m;
stack <int> s;
int delet[N];
vector <int> a[N];
void dfs(int u)
{
	for(int i=delet[u];i<a[u].size();i=delet[u])//遍历从u能够到达的点
	{
		delet[u]=i+1;
		dfs(a[u][i]);//搜索走到的点
	}
	s.push(u);//所有能到达的点都被处理过后,直接把u入栈
}
int main()
{
	int u,v,n,m;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;++i)
	{
		scanf("%d%d",&u,&v);
		a[u].push_back(v);
		chu[u]++;
		ru[v]++;	
	}//输入的同时统计每个点的入度和出度
	for(int i=1;i<=n;++i)
	{
		sort(a[i].begin(),a[i].end());	
	}//升序排列每一个点能达到的点的编号(用来应对字典序最小这一条件)
	int start=1;//起点位置预设为1(如果没有字典序的要求那么设在任意一个点都可以)
	bool flag=1;//flag==1表示存在欧拉回路,flag==1表示不存在欧拉路径或存在不是欧拉回路的欧拉路径
	int sum1=0,sum2=0;//sum1是“入度=出度-1”(有可能作为起点)的点的个数,sum2是“入度=出度+1”(有可能作为终点)的点的个数
	for(int i=1;i<=n;++i)
	{
		if(chu[i]!=ru[i]) flag=0;//判断是否是欧拉回路
		if(chu[i]-ru[i]>1)//出度入度之差大于1,肯定没有欧拉路径
		{
			printf("No");
			return 0;		
		}
		if(chu[i]-ru[i]==1)//统计sum1个数
		{
			start=i;
			sum1++;	
		}
		if(ru[i]-chu[i]==1) sum2++;//统计sum2个数
	}
	if(!(flag==1||(sum1==sum2)&&sum1==1))//不是欧拉回路或者普通欧拉路径中的任意一个
	{
		printf("No");
		return 0;	
	}
	dfs(start);//从起点开始不重不漏的dfs
	while(!s.empty())
	{
		printf("%d ",s.top());
		s.pop();	
	}//按序输出栈里的所有内容,即为所求
	return 0;	
}
posted @ 2021-08-15 14:36  Mint-hexagram  阅读(68)  评论(0编辑  收藏  举报