C++ [图论算法详解] 欧拉路&欧拉回路

这篇具有很好参考价值的文章主要介绍了C++ [图论算法详解] 欧拉路&欧拉回路。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

蒟蒻还在上课,所以文章更新的实在慢了点

那今天就来写一篇这周刚学的欧拉路和欧拉回路吧

C++ [图论算法详解] 欧拉路&欧拉回路

讲故事环节: 

一个风雪交加的夜晚

18世纪初普鲁士的哥尼斯堡,有一条河穿过,河上有两个小岛,有七座桥把两个岛与河岸联系起来。有个人提出一个问题:一个步行者怎样才能不重复、不遗漏地一次走完七座桥,最后回到出发点。后来大数学家欧拉把它转化成一个几何问题——一笔画问题。

C++ [图论算法详解] 欧拉路&欧拉回路

大概就是这么个图

就是现在人们所说的一笔画问题

回归题目

上面这个图太乱了,根本无法分析

C++ [图论算法详解] 欧拉路&欧拉回路

嗯~熟悉多了

难受多了 

现在的问题就是,如果不重复且不遗漏地走过所有的边(点可以无限次走,没有限制)

当然不指望你把它证明出来(bushi)

我们的大数学家欧拉,找到了它的充要条件

1.奇点的数目不是0个就是2个

奇点:就是度为奇数(如果是有向图就是入读+出度=奇数),反之为偶点

概念:

无向图:

欧拉路:对于一个图,每条边可以且只能访问一次

欧拉回路:在欧拉图的情况下,最后要回到原点。也就是说欧拉路不一定是欧拉回路,但欧拉回路一定是欧拉路

欧拉路有且只有0或2个奇点,欧拉回路不能有奇点。如果一个连通图有2n个奇点,那么这个图最少要k笔完成

有向图:

欧拉路:至多一个顶点入度和出度相差为1,其他顶点入度和出度全部相同

欧拉回路:每个顶点入度和出度都一样

举个栗子:

C++ [图论算法详解] 欧拉路&欧拉回路

假设一个图是一个“田”

每个拐角处都是一个点

按照上面说的,一个图有2n个奇点,这个图最少要k笔完成

C++ [图论算法详解] 欧拉路&欧拉回路 

这个图一共四个奇点,所以至少需要2笔完成

 解决方法:

1.dfs

第一步:判断图是否连通(不联通就啥也别说了)

第二步:判断奇点个数

很简单,但是使用dfs的话,就需要很多数组,并且用邻接矩阵是最方便的,所以费空间

2.并查集

分为G1和G2两个集合,G1表示已经联通的,G2表示未联通的

利用父亲表示法合并集合效率最高,也是上面那两步

代码:

并查集

#include<iostream>
using namespace std;

#define N 21

int e[N][N];
int du[N];
int total;
int path[405];
int pos;
int vis[N];
int n,m;

int father[N];
int h[N];

void make()
{
    for(int i=1;i<=n;i++)
    {
        h[i]=1;
        father[i]=i; 
    }   
}

int find(int a)
{
    if(father[a]!=a)
    {
        return father[a]=find(father[a]);
    }
    else
        return father[a];
}

void join(int a,int b)
{
   a=find(a);
   b=find(b);
   if(a==b) return;
   if(h[a]>=h[b]) 
   {
       father[b]=a;
       h[a]+=h[b];
       h[b]=0;
   }
   else if(h[a]<h[b])
   {
       father[a]=b;
       h[b]+=h[a];
       h[a]=0;
   }
}

void findpath(int s)
{
	for(int j=1;j<=n;j++)
	{
		if(e[s][j]==1)
		{
			e[s][j]=e[j][s]=0x7f;
			findpath(j);
		}
	}
	path[++pos]=s;
}

int main(){
	int a,b;
	cin>>n>>m;
	memset(e,0x7f,sizeof(e));
	make();


	for(int i=1;i<=m;i++)
	{
        cin>>a>>b;
		e[a][b]=e[b][a]=1;
        du[a]++;
		du[b]++;

		join(a,b);
	}

    int f=find(1);
	for(int i=2;i<=n;i++)
	{
        if(find(i)!=f)
		{
			cout<<"NO";
		    return 0;
		}
	}


	// if(h[f]!=n)
	// {
	// 	cout<<"NO";
	// 	return 0;
	// }

    total=0;
	int st=1;
	for(int i=1;i<=n;i++)
	{
		if(du[i]%2) 
		{
			total++;
			st=i;
		}
	}

	if(total!=0 && total!=2)
	{
		cout<<"NO";
		return 0;
	}

	findpath(st);


	for(int i=1;i<=pos;i++)
	{
		printf("%d ",path[i]);
	}
	
	return 0;
}

dfs深搜:


#include<iostream>
using namespace std;
#define N 21
int e[N][N];
int du[N];
int total;
int path[405];
int pos;
int vis[N];
int n,m;

void dfs(int i)
{
    vis[i]=true;
	total++;
	for(int j=1;j<=n;j++)
	{
		if(e[i][j]==1 && !vis[j]) 
		    dfs(j);
	}
}

void findpath(int s)
{
	for(int j=1;j<=n;j++)
	{
		if(e[s][j]==1)
		{
			e[s][j]=e[j][s]=0x7f;
			findpath(j);
		}
	}
	path[++pos]=s;
}

int main(){
	int a,b;
	cin>>n>>m;
	memset(e,0x7f,sizeof(e));
	for(int i=1;i<=m;i++)
	{
        cin>>a>>b;
		e[a][b]=e[b][a]=1;
        du[a]++;
		du[b]++;
	}

	dfs(1);
	if(total!=n)
	{
		cout<<"NO";
		return 0;
	}

    total=0;
	int st=1;
	for(int i=1;i<=n;i++)
	{
		if(du[i]&1) 
		{
			total++;
			st=i;
		}
	}
    
	if(total!=0 && total!=2) 
	{
		cout<<"NO";
		return 0;
	}

	findpath(st);

	for(int i=1;i<=pos;i++)
	{
		printf("%d ",path[i]);
	}

	return 0;
}

例题:

题目描述

如果一个无向图存在一笔画,则一笔画的路径叫做欧拉路,如果最后又回到起点,那这个路径叫做欧拉回路。

输入

第一行n,m,0 < n <=20,表示有n个点,m条边,以下m行描述每条边连接的两点。

输出

如果有欧拉路或欧拉回路,输出一条路径即可,顶点之间由空格隔开。

如果没有,输出NO
 

样例输入1

5 5
1 2
2 3
3 4
4 5
5 1

样例输出1

1 5 4 3 2 1

 


 

这题直接套模板就没问题

分析优劣点:

 1.dfs

简单,实用

费空间费时间

2.并查集

效率高,快速,不费时间不费空间

难,费劲文章来源地址https://www.toymoban.com/news/detail-412689.html

到了这里,关于C++ [图论算法详解] 欧拉路&欧拉回路的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 图论中回路与圈的概念区分

    第一种定义方法 迹 是边不重复的通路,但是顶点可以重复。 回路 是首尾顶点相同的迹。 路 是顶点不重复的迹,即边和顶点都不重复的通路,但是首尾顶点可以相同。 圈 是首尾顶点相同的路。 第二种定义方法 回路:起点终点相同 简单通路:起点到终点所经过的 边不同 

    2024年02月04日
    浏览(32)
  • 数据结构第13周 :( 迪杰斯特拉最短路径 + 弗洛伊德求最短路径 + 欧拉回路 + Invitation Cards)

    【问题描述】 在带权有向图G中,给定一个源点v,求从v到G中的其余各顶点的最短路径问题,叫做单源点的最短路径问题。 在常用的单源点最短路径算法中,迪杰斯特拉算法是最为常用的一种,是一种按照路径长度递增的次序产生最短路径的算法。 在本题中,读入一个有向图

    2024年02月13日
    浏览(25)
  • 图论10-哈密尔顿回路和哈密尔顿路径+状态压缩+记忆化搜索

    求解哈密尔顿回路 如何求解一个图是否存在哈密尔顿回路呢? 一个最直观的想法就是暴力求解。暴力求解的思路也很简单:我们遍历图的每一个顶点 v,然后从顶点 v 出发,看是否能够找到一条哈密尔顿回路。 暴力求解的代价同求解全排列问题是等价的,其时间复杂度为

    2024年02月04日
    浏览(26)
  • 图论(欧拉路径)

    理论: 所有边都经过一次,若欧拉路径,起点终点相同,欧拉回路 有向图欧拉路径:恰好一个out=in+1,一个in=out+1,其余in=out 有向图欧拉回路:所有in=out 无向图欧拉路径:两个点度数奇,其余偶 无向图欧拉回路:全偶 基础练习 P7771 【模板】欧拉路径 P2731 [USACO3.3] 骑马修栅栏

    2024年02月05日
    浏览(22)
  • 离散数学 --- 图论基础 --- 图的同构,通路与回路,可达性与最短通路

    同一个图(这里的图是抽象的数学定义)可以有不同的图形表示方法 1.重数:两点之间的平行边的个数   1.得到 n! 的过程,一个图中的一个结点在另一个图中对应的结点有n种可能(黄框中定义的图来讨论),这个对应好后下一个结点有 n - 1 种可能,再下一个有n-2种,直到最

    2024年01月25日
    浏览(27)
  • 【C++算法竞赛 · 图论】图论基础

    前言 图论基础 图的相关概念 图的定义 图的分类 按数量分类: 按边的类型分类: 边权 简单图 度 路径 连通 无向图 有向图 图的存储 方法概述 代码 复杂度 图论(Graph theory) ,是 OI 中的一样很大的一个模块,围绕它有很多高难度的算法以及高级的概念。 这篇文章将介绍关

    2024年04月12日
    浏览(33)
  • 图论——浅谈理论,DFS序和欧拉序

    提示:本文在树论基础上。 DFS 序:1 2 4 5 7 9 8 3 6. 欧拉序:1 2 4 4 5 7 9 9 7 8 8 5 2 3 6 6 3 1. 回加欧拉序 :1 2 4 2 5 7 9 7 5 8 5 2 1 2 3 6 3 1. 下文举例均指此图。 周所周知,DFS 为深度优先遍历,其框架如: 而 DFS 序就表示,DFS 遍历节点的顺序。 比如第 3 个遍历到的节点为 Q,则 DFS 序

    2024年01月19日
    浏览(30)
  • 离散数学 | 图论 | 欧拉图 | 哈密顿图 | 割点 | 桥(欧拉图和哈密顿图有没有割点和桥?)

    本文主要解决以下几个问题: 1.欧拉图能不能有割点,能不能有桥? 2.哈密顿图能不能有割点,能不能有桥? 首先我们要明白几个定义 割点 的定义就是在一个图G中,它本来是连通的,去掉一个点v以后这个图G就不连通了,那么点v就被叫做 割点 。 桥 的定义就是在一个图G中

    2024年02月08日
    浏览(28)
  • 【算法/图论】2-SAT问题详解

    在了解2-SAT的定义之前,我们需要给出一些基础定义。 布尔变量 (Boolean variable):只能取 1 1 1 (true)或 0 0 0 (false)的变量。 否定连接词 ¬ neg ¬ (negation):取布尔变量的否定。例如 ¬ 1 = 0 neg1=0 ¬1 = 0 , ¬ 0 = 1 neg0=1 ¬0 = 1 。 ¬ ( ¬ a ) = a neg(neg a)=a ¬ ( ¬ a ) = a 。 合取

    2024年02月02日
    浏览(26)
  • 算法——弗洛伊德算法(Floyd-Warshall)(图论)(c++)

    (蒟蒻的第四篇文章,希望dalao勿喷) (希望没问题) 声明: 1.本人变量定义的名称很low 2.本人用的方法也很low 3.但我觉得文章应该不low  (盲目自信) 第四篇文章讲讲Floyd算法 Floyd算法是一种寻找最短路径的常见算法,其特点是: 短,好理解(虽然其他算法也挺好理解的

    2023年04月09日
    浏览(25)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包