算法学习之--图论基础

【图论——第一讲】图论基础以及图的储存 ฅ(๑˙o˙๑)ฅ 大家好, 欢迎大家光临我的博客:面向阿尼亚学习算法学习笔记系列持续更新中~ 文章目录 一、前言推荐大家一个图形编译器[很好用](https://csacademy.com/ap... 阅读详情

1.图论基础

  一个图由顶点集(V)和边集(E)组成,每一条边就是一个点对(v,w),其中v,w\epsilon V。如果点对是有序的(即v,w与w,v不同),那么图就是有向图,否则称作无向图(无向图是特殊的有向图)。如果在边集中允许出现(w,w)这种一个顶点的点对,这种边称为自环边。如果边集中允许出现多组相同的点对,这样的边称为平行边。

2.图的表示

  图的表示实际上就是对图中边的存储,每条边由两个顶点组成 

  (1)邻接矩阵:假设图中有n个顶点,那么图中的边有(n*n)种可能,使用n*n的二维矩阵(bool[][])来存储边,每一行(列)表示当前顶点与图中所有其他顶点之间的邻接关系,[i][j]为true表示图中存在点对(i,j)的边,否则表示不存在。由于在二维矩阵中[i][j]有且只有一个位置与之对应,因此邻接矩阵的实现消除了平行边

  (2)邻接表:假设图中有n个顶点,使用n个int数组存储与当前顶点邻接的所有点

在实际应用中,对于稠密图一般使用邻接矩阵来实现,对于稀疏图一般使用邻接表来实现。(判断是稠密图还是稀疏图的标准是每个顶点的实际连接数与理论最大连接数相比)。 

代码实现如下:

SparseGraph(稀疏图)

//稀疏图,用邻接表实现(允许存在平行边,允许存在自环边)
class SparseGraph
{

private:

	int mp_vertexCount;	//顶点个数

	int mp_edgeCount; //边条数

	bool isDirected;	//是否为有向图

	vector<vector<int>> mp_graph;	

public:
	SparseGraph(int n,bool isDirected)
	{
		mp_vertexCount = n;
		mp_edgeCount = 0;
		this->isDirected = isDirected;
		mp_graph = vector<vector<int>>(n,vector<int>());
	}

	~SparseGraph(void){}

	int V(){return mp_vertexCount;}	//返回顶点个数
	int E(){return mp_edgeCount;} //返回边条数

	//添加一条边
	void addEdge(int v,int w)
	{
		mp_graph[v].push_back(w);	//不判断是否已经存在边,过于损耗程序性能,因此该实现允许存在平行边
		if(v!=w && !isDirected)	//对于自环边,不需要再次插入反向边
			mp_graph[w].push_back(v);
		mp_edgeCount++;
	}

	// 验证图中是否有从v到w的边,最差情况下时间复杂度O(V)
	bool hasEdge( int v , int w ){
		//对于无向边,由于在插入时保证了反向边的加入,因此在判断是否存在边时无须再次区分有(无)向图
		assert( v >= 0 && v < n );
		assert( w >= 0 && w < n );

		for( int i = 0 ; i < mp_graph[v].size() ; i ++ )
			if( mp_graph[v][i] == w )
				return true;
		return false;
	}

	//打印输出边
	void show()
	{
		for(int i=0;i<mp_vertexCount;i++)
		{
			cout<<i<<": ";
			for(int j=0;j<mp_graph[i].size();j++)
			{
				cout<<mp_graph[i][j]<<",";
			}
			cout<<endl;
		}
	}
	

	//稀疏图迭代器,传入一个图和一个顶点
	class adjIterator
	{
	private:
		//目标顶点所在图
		SparseGraph &G;
		//指示当前遍历的位置
		int index;
		//要遍历的顶点
		int v;

	public:

		adjIterator(SparseGraph& graph,int v):G(graph)
		{
			this->index = 0;
			this->v = v;
		}

		~adjIterator()
		{
		}

		//返回目标顶点的邻接表中第一个顶点
		int begin()
		{
			this->index = 0;	//begin可能会多次调用
			if(G.mp_graph[v].size() >0)
				return G.mp_graph[v][index];
			return -1;
		}

		//是否已经遍历到目标顶点邻接表尾部
		bool end()
		{
			return this->index >= G.mp_graph[v].size();
		}

		//返回目标顶点邻接表中的下一个顶点
		int next()
		{
			index++;
			if(index < G.mp_graph[v].size())
			{
				return G.mp_graph[v][index];
			}
			return -1;
		}
	};
};

DenseGraph(稠密图)

//稠密图,使用邻接矩阵实现(不存在平行边,允许存在自环边)
class DenseGraph
{
private:

	//图的总顶点个数
	int mp_vertexCount;

	//图的边计数
	int mp_edgeCount;

	//是否为有向图
	bool mp_isDirected;

	//图的具体数据(顶点之间的连接关系),一个mp_vertexCount*mp_vertexCount矩阵
	vector<vector<bool>> mp_graph;

public:
	//vertexCount为顶点数,isDirected是否为有向图
	DenseGraph(int vertexCount,bool isDirected)
	{
		mp_vertexCount = vertexCount;
		mp_edgeCount = 0;
		mp_isDirected = isDirected;
		mp_graph = vector<vector<bool>>(vertexCount,vector<bool>(vertexCount,false));	//初始化顶点之间全不连接(即没有边)
	}

	~DenseGraph(void)
	{

	}

	int E(){return mp_edgeCount;}	//返回边条数
	int V(){return mp_vertexCount;}	//返顶点的个数

	//向图中添加边
	void addEdge(int v,int w)
	{
		assert(v>=0 && v<=mp_vertexCount-1);
		assert(w>=0 && w<=mp_vertexCount-1);
		if(hasEdge(v,w))	//添加边已存在
			return;

		mp_graph[v][w] = true;
		if(!mp_isDirected)	//无向图,添加反向连接
		{
			mp_graph[w][v] = true;
		}
		mp_edgeCount++;
	}

	//判断两顶点是否连接,时间复杂度O(1)
	bool hasEdge(int v,int w)
	{
		assert(v>=0 && v<=mp_vertexCount-1);
		assert(w>=0 && w<=mp_vertexCount-1);
		return mp_graph[v][w];
	}

	//打印输出图中所有边
	void show()
	{
		for(int i=0;i<mp_vertexCount;i++)
		{
			cout<<i<<": ";
			for(int j=0;j<mp_vertexCount;j++)
			{
				cout<<mp_graph[i][j]<<",";
			}
			cout<<endl;
		}
	}

	class adjIterator
	{

	private:
		//目标顶点所在图
		DenseGraph& G;
		//当前遍历位置
		int index;
		//遍历的目标顶点
		int v;

	public:
		adjIterator(DenseGraph& graph,int v):G(graph)
		{
			assert(v>=0 && v<graph.V());
			this->v = v;
			this->index = -1;	//邻接矩阵中,顶点所在行的第一个连接顶点不一定从0开始
		}
		

		~adjIterator()
		{}

		//邻接矩阵中
		int begin()
		{
			index = -1;		//begin可能会多次调用
			return next();	
		}

		bool end()
		{
			return index >= G.V();
		}

		int next()
		{
			for(index++;index<G.V();index++)	//遍历邻接矩阵中v顶点所在行,返回值为true的索引
			{
				if(G.mp_graph[v][index])
					return index;
			}
			return -1;
		}
	};
};

3.图的深度优先遍历:

  基本思路:递归遍历图中指定顶点的邻接顶点,用bool数组标记图中顶点是否已被遍历过。深度遍历可用于求图的联通分量,借助于联通分量我们又可以求得两顶点是否存在路径,使用int数组记录每个顶点所属的联通分量。


template <typename Graph>
class Component
{
public:
	//构造函数中求出联通分量
	Component(Graph& graph):G(graph)
	{
		visited = new bool[G.V()];
		id = new int[G.V()];
		for(int i=0;i<G.V();i++)
		{
			visited[i] = false;
			id[i] = -1;
		}
		ccount = 0;

		for(int i=0;i<G.V();i++)
		{
			if(!visited[i])
			{
				depthFirstSearch(i);
				ccount++; 
			}
		}
	}
	~Component()
	{
		if(visited)
		{
			delete[] visited;
		}
		if(id)
		{
			delete[] id;
		}
	}

	//判断两顶点是否联通(是否属于同一联通分量)
	bool isConnected(int v,int w)
	{
		assert(v>=0 && v<G.V());
		assert(w>=0 && w<G.V());
		return id[v]==id[w];
	}

	int count()
	{
		return ccount;
	}
private:

	//深度优先遍历
	void depthFirstSearch(int i)
	{
		id[i] = ccount;	//赋值联通分量
		visited[i] = true;	//标记当前节点为已访问过
		Graph::adjIterator ite(G,i);
		for(int i=ite.begin();!ite.end();i=ite.next())
		{
			if(!visited[i])
				depthFirstSearch(i);	//使用递归实现深度优先,继续遍历连接节点的连接节点
		}
	}

private:
	//要遍历的图
	Graph& G;
	//记录元素是否被访问过
	bool* visited;
	//联通分量
	int ccount;
	//每个顶点对应的联通分量标记
	int* id;

};

4.获取图中的路径

在遍历的基础上,我们可以使用一个int数组来记录当前顶点是由哪个顶点遍历而来,即int* from,from[i]=v表示在当前图的遍历中,顶点i是在遍历顶点v的邻接顶时被访问到。如果要求到任意顶点m的路径,只需要根据from[i] = m反推回去,就可以得到一条完整的路径。下面给出代码实现:

template<typename Graph>
class Path
{
public:
	Path(Graph& graph,int source):G(graph)
	{
		//初始化
		this->s = source;
		visited = new int[G.V()];
		from = new int[G.V()];
		for(int i=0;i<G.V();i++)
		{
			visited[i] = false;
			from[i] = -1;
		}
		//深度优先遍历source源顶点
		depthFirstSearch(source);
	}
	~Path(void)
	{
		delete[] visited;
		delete[] from;
	}

	//顶点v与源顶点是否存在连通路径
	bool hasPath(int v)
	{
		return visited[v];
	}

	//获取顶点v与源顶点连通路径
	void path(int v,vector<int> &vec)
	{
		stack<int> _stack;
		int p = v;
		while(p!=-1)
		{
			_stack.push(p);
			p = from[p];
		}
		vec.clear();
		while(!_stack.empty())
		{
			vec.push_back(_stack.top());
			_stack.pop();
		}
	}

	// 打印出从s点到w点的路径
	void showPath(int w)
	{
		assert( hasPath(w) );
		vector<int> vec;
		path( w , vec );
		for( int i = 0 ; i < vec.size() ; i ++ ){
			cout<<vec[i];
			if( i == vec.size() - 1 )
				cout<<endl;
			else
				cout<<" -> ";
		}
	}

private:

	//深度优先遍历
	void depthFirstSearch(int v)
	{
		visited[v] = true;	//标记当前节点为已访问过
		Graph::adjIterator ite(G,v);
		for(int i=ite.begin();!ite.end();i=ite.next())
		{
			if(!visited[i])
			{
				from[i] = v;
				depthFirstSearch(i);	//使用递归实现深度优先,继续遍历连接节点的连接节点
			}
		}
	}

private:

	//寻路的图
	Graph& G;

	//起始点
	int s;

	//标记顶点是否被访问过的数据
	int* visited;

	//记录遍历到的每个顶点的从哪个顶点索引到
	int* from;

};

5.获取最短路径(广度优先遍历)

基本思路:遍历到每一个顶点时先将其所有邻接顶点加入遍历队列中并出队当前顶点,按照队列中的顺序遍历顶点,队列为空时遍历完成。代码实现如下:

//获取无权图中两顶点间的最短路径(使用广度优先遍历)
template<typename Graph>
class ShortestPath
{
private:

	Graph& G;	//要遍历的图

	int s;	//起始点

	bool* visited;	//标记顶点是否在遍历队列中

	int* from;	//记录路径,from[i]表示查找路径上i的上一个顶点

	int* ord;	//记录路径中,节点的次序(即距离起始顶点的距离)

public:

	ShortestPath(Graph& graph,int s):G(graph)
	{
		this->s = s;
		visited = new bool[G.V()];
		from = new int [G.V()];
		ord = new int[G.V()];
		for(int i=0;i<G.V();i++)
		{
			visited[i] = false;
			from[i] = -1;
			ord[i] = -1;
		}

		//遍历队列
		std::queue<int> queue;
		queue.push(s);
		ord[s] = 0;
		visited[s] = true;
		while(!queue.empty())
		{
			int v = queue.front();
			queue.pop();

			Graph::adjIterator adjIte(G,v);
			for(int i=adjIte.begin();!adjIte.end();i=adjIte.next())
			{
				if(!visited[i])
				{
					queue.push(i);
					from[i] = v;
					visited[i] = true;
					ord[i] = ord[v]+1;
				}
			}
		}
	}


	~ShortestPath(void)
	{
		delete[] visited;
		delete[] from;
		delete[] ord;
	}


	//获取顶点v与源顶点连通路径
	void path(int v,vector<int> &vec)
	{
		stack<int> _stack;
		int p = v;
		while(p!=-1)
		{
			_stack.push(p);
			p = from[p];
		}
		vec.clear();
		while(!_stack.empty())
		{
			vec.push_back(_stack.top());
			_stack.pop();
		}
	}

	// 打印出从s点到w点的路径
	void showPath(int w)
	{
		vector<int> vec;
		path( w , vec );
		for( int i = 0 ; i < vec.size() ; i ++ ){
			cout<<vec[i];
			if( i == vec.size() - 1 )
				cout<<endl;
			else
				cout<<" -> ";
		}
	}

 

《算法和数据结构》从语言到算法的过渡篇_当语言学到什么程度可以开始学算法了 看到太多爆肝熬夜整合的内容,又是几万字,又是爆肝,我也来试试看能不能扛得住。试完后发现,果然还是扛不住啊。但是既然整理完了,那就把我的算法学习路线发出来吧,我把整个算法学习的阶段总结成了五个步骤,分别为:「 基础语法 」「 语法练习 」「 数据结构 」「 算法入门 」「 算法进阶 」。本文梳理了这五个大项的思维导图,在下文会有详细介绍。希望各位能够找到自己的定位,通过自己的努力在算法这条路上越走越远。刚开始切勿心浮气躁,说一定要把这么多东西都学会。就算你的精力旺盛,日夜操劳,时间也是有限的。 阅读详情

相关推荐

图论基础知识总结

图是由节点和连接节点之间的边组成的,与连线的长度,节点的位置没有关系。一个图是一个三元组,其中V是一个非空的节点集合,E是边集合,F是从边集合E到节点序偶(无序偶或有序偶)集合上的函数。若图中边总是两个节点的关联,则图可简记为G=。树可以是空树但图不能是空图。图的结点集不能为空但边集可以为空。**无向图:**若图中所有边都是无向边,则图是无向图; **有向图:**若所有边都是有向边,则图是有向图; **混合图:**若图中既有无向边又有无向边则图为混合图; **多重图...

欢迎订阅 -- 小源笔迹 7908

图论基本知识

一.概述 图论(Graph Theory)是数学的一个分支。它以图为研究对象。图论中的图是由若干给定的点及连接两点的线所构成的图形,这种图形通常用来描述某些实体之间的某种特定关系,用点代表实体,用连接两点的线表示两个实体间具有的某种关系。 相比矩阵、张量、序列等结构,图结构可以有效建模和解决社会关系、交通网络、文法结构和论文引用等需要考虑实体间关系的各种实际问题。(关键词:实体间关系) 二.图的基本表示(Graph Representations) 图(Graph) ...

Mitsui14wung的博客 4万+

SWMM建模与案例应用

4、排水系统控制规则通过控制功能,可以在模拟进行过程中,通过条件判断,对闸门、水泵、管道、孔口、堰进行控制,实现排水系统实时控制。5、SWMM与其他模型对比分析分析:STORM、MOUSE、Info Works、SUSTAIN、SWC。1、模型初始设置主要参数:雨量计、汇水区、节点、出水口、管渠、分流器、蓄水池等参数前缀的设置。2、气象数据设置温度、蒸发、风速、融雪、面积亏损、气候调整、雨量计。1、多软件数据交互:CAD、Arcgis、SWMM。(1)节点、管段、水泵、孔口、堰、雨水口和街道。

m0_74575633的博客 3421

图论(一)基本概念

图(graph)是数据结构和算法学中最强大的框架之一(或许没有之一)。图几乎可以用来表现所有类型的结构或系统,从交通网络到通信网络,从下棋游戏到最优流程,从任务分配到人际交互网络,图都有广阔的用武之地。 而要进入图论的世界,清晰、准确的基本概念是必须的前提和基础。下面对其最核心和最重要的概念作出说明。关于图论的概念异乎寻常的多,先掌握下面最核心最重要的,足够开展一些工作了,其它的再到实践中不断去

saltriver的专栏 15万+

Langchain4j 文档处理实战:从加载到分割的完整流程解析

本文详细解析了使用Langchain4j进行文档处理的完整流程,涵盖从文档加载、解析到分割的核心步骤。通过实战代码示例,重点介绍了如何利用文档分割器将大文档切割为适合大语言模型处理的片段,并提供了参数调优与避坑指南,帮助Java开发者高效构建AI应用的数据处理基础。

smartcontract5的博客 542

国宇测试盒GH7009 SPI读操作全解析:从接线到代码实现的避坑指南

本文详细解析了国宇GH7009测试盒进行SPI读操作的完整流程与避坑要点。重点阐述了硬件连接中IO2时序控制引脚的关键作用,提供了从接线方案、电源处理到上位机代码实现的实战指南,并针对常见的数据不稳定、特定寄存器读取失败等问题给出了具体解决方案。

dapp9builder的博客 223

算法学习之路的心得五之图论基础

GDUT 20 寒假集训专题5.图论基础 总结 题目题解 1.图的存储 目前我所知道的图的存储大致有三种, 第一种是用一个二维数组G[n] [m],对应的两个点如果有边就对应的赋值,但是要注意题目所给的是有向还是无向,有时候两个点之间有多重条边,这时候用二维数组来存的图就很高效的更新最短边(最长边)的值。 第二种是用stl里面的vector,设置一个v[n],来存图,用这个来存的优点是高效利用空间,还有后期搜索所有边也方便, 第三种是适合边中有多个条件,比如一条路里面有经过所需的时间,还有过路费,这时候

cascacasc的博客 350

Visual Studio Git 使用指南

Visual Studio 2022深度集成了Git功能,提供了直观的图形界面管理源代码。本文详细介绍了VS中Git的使用方法:从环境准备、克隆/创建仓库开始,重点讲解了"Git更改"窗口的日常操作,包括查看修改、暂存文件、提交推送等。同时涵盖了分支管理、查看历史、解决冲突等核心功能,以及储藏、重置等高级操作。文章还提供了实用技巧,如提交规范、频繁提交等最佳实践。VS的Git集成覆盖了日常开发需求,图形界面与命令行可互补使用,适合各层次开发者高效管理代码版本。

guigenyi的专栏 1570

网络算法:从图论基础到深度学习应用(万字长文)

摘要 本文系统介绍了网络算法的知识体系,从基础图论到前沿图神经网络。首先讲解了图的基本概念、表示方法和度量指标。然后详细阐述了经典算法:图的遍历(BFS/DFS)、最短路径(Dijkstra/Bellman-Ford)、最小生成树(Kruskal/Prim)、网络流和社区发现。接着分析了传统方法的局限性,引出深度学习在图数据上的应用,重点介绍了图表示学习(如Node2Vec)和图神经网络(GCN)的核心原理——消息传递机制。全文构建了从理论基础到实践应用的完整框架,为处理各类网络数据问题提供了方法论指导。

热爱技术与前沿创新,深耕科技领域,在科创中精进自我;探索技术乐趣,分享技术干货与成长心得,以技术为伴,热爱生活,在科创与生活中双向成长。 267

FreeFEM++下载安装和使用

最近要利用机器学习求解一些偏微分方程,对于一些复杂的偏微分方程,需要一些精度比较高的参考解,导师推荐了FreeFEM++软件。首次使用,特此记录一下,以备以后查阅。 1、FreeFEM++简介 FreeFEM是开源的有限元模拟系统,有法国利翁斯实验室、埃尔和玛丽居里大学共同开发,在世界范围内广泛使用。 2、FreeFEM++去何处下载? 下载地址:https://freefem.org/ 点击Download,然后会跳转到 https://github.com/FreeFem/FreeFem-source

夜晓岚的博客 1万+

Gmsh+OCC对应版本库编译

输入 GMSH_DLL_EXPORT值C:\LIB\OCCT-7_8_0-i;9、如果只是生成库文件编译gmesh工程即可生成文件在C:\LIB\Gmsh\gmsh-4.13.1-Windows64-B\Debug 下gmsh.dll、gmsh.lib、gmsh.h、gmshc.h文件;3、CMAK编译Gmsh对应OCC版本的,CMAK选择源文件路径C:\LIB\Gmsh\gmsh-4.13.1-source,生成构建文件路径C:\LIB\Gmsh\gmsh-4.13.1-Windows64-B。

u013401364的博客 412

01.图论基础,图算法与图机器学习概况介绍

文章目录课程简介图的概念 课程简介 炼数课程网站就不贴了,以下是原课程介绍。后续将在这个专栏记录一些笔记和作业。 图诞生为一个简洁的数学概念:节点和节点之间关系的集合。如今图已经被广泛应用于建模许多真实世界的场景——从社交网络的人际关系,到信用卡的欺诈行为监测,再到遗传学与疾病检测,图无处不在。相比于其他的数据结构,图数据的一个重要的特性:图数据包含大量有价值的关系数据。然而,许多之前的机器学习模型往往只关注每个样本的特征,而没有考虑到样本之间的关系数据或没有很好的方法来利用和建模这些关系数据。图机器学习就

老毛的博客 2491

Zemax与Matlab交互:双胶合优化详细流程

Zemax与Matlab交互:双胶合优化详细流程

weixin_72050316的博客 629

课程学习--算法总结 图论算法(第1期)--理论基础

一、 图论 图论 (Graph theory) 是数学的一个分支,图是图论的主要研究对象。 图 (Graph) 是由若干给定的顶点及连接两顶点的边所构成的图形,这种图形通常用来描述某些事物之间的某种特定关系。 顶点用于代表事物,连接两顶点的边则用于表示两个事物间具有这种关系。图的类型 二、 常用类型 有向图 无向图 有环图 赋权图(如果这些权都是正实数,就称为正权图) 其他类型 混合图(即有向又无向) 多重图(有平行边,两节点之间有两条边) 线图(无平行边) 简单图(线图并且是无环图) 多重图(有自环或重

查理的博客 994

最强游戏投屏串流搭档Sunshine+Moonlight配置方法

因祸得福的是,sunshine作为开源的self-host的服务端,不仅可以代替Novidia的服务端角色,还拓展了moonlight可以服务的主机,非novidia显卡的PC也可以通过这对搭档实现高质量的游戏窜流投屏了。回到moonlight,点击电脑图表,会给你一个Pincode,到Sunshine控制台,菜单点击Pin,输入moonlight给出的pin码。高质量的图像: Moonlight支持高清(HD)和甚至4K分辨率的投屏,同时还提供了对音频的传输支持,确保用户可以享受到高质量的视频和音频。

每日出拳老爷子的博客 1万+

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

算法学习笔记-----图论基础

除了 1 之外可能还有入度为 0 的点,因此要在跑拓扑排序前先把这些点对结果的影响消除。拓扑排序只能在 DAG 上进行,有向才能确定删除的顺序,无环才能保证排序过程正确进行,如果有环的话会导致排序到某一步出现没有入度为 0 的点。拓扑排序的结果不唯一,例如在上图中,a-e-b-c-d 或 a-b-e-c-d 或 a-b-c-e-d 都是正确的答案。求食物链的总数,必须从生产者开始,到最高级消费者结束,模拟拓扑排序的过程即可。拓扑排序:每次选入度为 0 的点,删除它和它的出边。两种遍历:dfs,bfs。

jinxdtaiy的博客 717

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

通过掌握 DFS 和 BFS 算法,可有效解决图论中的各类基础问题,是进一步学习复杂图算法的基础

图的遍历是指从图中的某一顶点出发,按照某种搜索方法沿着图中的边访问图中的所有顶点,且每个顶点仅被访问一次的过程。它是图论中的核心操作之一,广泛应用于路径查找、拓扑排序、连通性分析等场景。常见的图遍历算法主要有**深度优先搜索(DFS)** 和**广度优先搜索(BFS)** 两种。

[Blog][Domain] programb.blog.youkuaiyun.com 894

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

【笔面试算法学习专栏】图论算法基础:DFS、BFS与并查集

DFS:递归实现,用栈模拟,适用于连通性检测BFS:层序遍历,用队列实现,适用于最短路径并查集:集合合并与查询,适用于动态连通性。

m0_50709695的博客 257

【图论算法】零基础最小生成树学习与总结

参考资料和引用来源 数据结构–最小生成树详解 AcWing 858. Prim算法求最小生成树:图解+详细代码注释(带上了保存路径) AcWing 858. Prim算法求最小生成树 的视频 AcWing 859. Kruskal算法求最小生成树 什么是最小生成树 现在假设有一个很实际的问题:我们要在n个城市中建立一个通信网络,则连通这n个城市需要布置n-1一条通信线路,这个时候我们需要考虑如何在成本最低的情况下建立这个通信网? 于是我们就可以引入连通图来解决我们遇到的问题,n个城市就是图上的n个顶点,然

karshey的博客 671

【算法竞赛学习笔记】树上问题基础-超有用的图论详解

title :树上问题基础 tags : ACM,图论 date : 2021-11-6 author : Linno 基本概念 树的深度:从树根往下数,叶子节点所在的最大层数称为树的深度。(有教材定义不一样,看题意吧。要区分高度) 树的直径:树中两节点距离的最大值称为树的直径。 子树大小:对每一个节点的大小都等于左子树大小+右子树大小+1(自己) 节点重量:删去该节点后,所有树大小的最大值。即该节点所有子树大小的最大值称为节点重量。 求树的直径 做法1:两遍dfs const int N = 1000.

SC_Linno的博客 799

图论学习总结(For XCPC)

图论个人学习总结,这篇博客所涉及到的题目基本包含蓝书图论的所有例题,还包括牛客上的一些题目(包括少部分多校题)以及个人XCPC训练或比赛时​遇到的一些图论题

ChuanhuaYu的博客 1729

acwing 算法基础班学习笔记-第三讲.搜索和图论

一、DFS 深度优先遍历,需要维护一个st数组来表示每个节点是否被访问过,若不止一条路径则还需要恢复st数组的值(恢复状态)。剪枝:当遍历除了节点是否被访问以外还有其他条件时,可同时判断条件是否成立和节点是否被访问,若不成立则跳过该节点,最后只返回走到终点的路径。 树和图的深度优先遍历问题: 树的重心。可用节点的子节点个数s代表一个子连通分量,n-s代表除去这个节点和其子节点外其他所有节点的个数,迭代更新。 二、BFS 广度优先遍历,将每次可操作的状态压入队列,若队列非空则访问队头元素,距离+1。注意八数码

irony_202的博客 768

【算法竞赛学习笔记】拓扑排序与关键路径-图论基础

title : 拓扑排序与关键路径 date : 2021-8-15 tags : ACM,图论 author : Linno 拓扑排序 对一个有向无环图G中所有顶点排成一个序列,使得图中任意一对顶点u和v,若边(u,v)属于E(G),那么u再线性序列中出现在v之前。这样的线性序列称为满足拓扑排序(Topological Order)的序列,简称拓扑序列。简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序。 实现方法 //BFS:寻找入度为0的点,把这个点加入队列,在队列中对.

SC_Linno的博客 454

图论及其应用答案简介

图论及其应用答案简介 去发现同类优质开源项目:https://gitcode.com/ 此仓库包含了图论及其应用的详细答案资源,主要内容包括讲义和例题的解析与讲解。本资源旨在为学习图论的学生和研究者提供帮助,希望能对您在学习过程中遇到的难题提供解答和启示。 资源文件涵盖了图论的基础理论、典型应用以及相关算法,通过详细解析例题,帮助读者更好地理解和掌握图论知识。我们相信,这份答案资源将成为您学习图论...

gitblog_06730的博客 524

【机器学习|数学基础】Mathematics for Machine Learning系列之图论(6):生成树算法

2.5 生成树算法 2.5.1 构造生成树的方法 求连通图的生成树的两种方法: 破圈法 避圈法 破圈法 从连通图GGG开始,若GGG中含有圈,则去掉圈上的一边 若GGG中还有圈,再去掉圈上的一条边 重复上面步骤,直至GGG中不含圈为止 最后得到的便是GGG的不含圈的连通生成子图,即生成树 避圈法 在GGG中任选一条边e1e_1e1​ 然后找一条不与e1e_1e1​形成圈的边e2e_2e2​,得到{e1,e2}\{e_1,e_2\}{e1​,e2​} 再找一条不与{e1,e2}\{e_1,e_2\

海到无边天作岸 山登绝顶我为峰 2287
上一篇: 算法学习之--并查集
下一篇: 2.着色器(shader)
angry ant
博客等级 码龄10年 9粉丝 53原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值