DFS相关的一些模板

c++深度优先搜索DFS 深度优先搜索,又叫DFS,是遍历图或者数的一种算法,本质就是递归。具体方法:先以一个节点为起点,向一个方向扩展,再以新的节点为起点,向一个方向扩展,直到这个方向不满足条件,或者到达这个方向的最深,再往回走,叫做回溯。然后扩展另一个方向,知道整个图都遍历完成。所以叫做深度优先搜索。这种算法极其重要,是每一个会编程的人都必须掌握的一种算法。因为许多东西都可以用它来实现。比如树的遍历,图的遍历,全排列。而且很多题目,如果你不会或者想不出正解,就可以用深搜暴力一下,也能骗得部分分。 阅读详情
/*请从main开始看*/

/*
SampleInput:

6 8 7
0 5
2 4
2 3
1 2
0 1
3 4
3 5
0 2
1 4
0 0
1 1
2 2
3 3
4 4
5 5
4 2 2
0 1
2 3
2 1
0 0

*/

#include<cstdio>
#include<cstring>
#include<list>
#include<stack>
#include<set>
using namespace std;
const int maxn = 100002;

list<int> point[maxn];///当然,你也可以使用vector实现
set<int> cc[maxn];///cc指连通分量
bool vis[maxn], color[maxn];
int edgeTo[maxn];///dfs出的路径
stack<int> path;
int beg, end, count;
bool isend, hascycle, isTwoColorable;

///复杂度:O(V+E)
///找路,从v到end
void dfs(int v)
{
	vis[v] = true;
	list<int>::iterator it;
	for (it = point[v].begin(); it != point[v].end(); ++it)
	{
		if (isend)
			return;
		int w = (int) * it;
		if (!vis[w])
		{
			edgeTo[w] = v;
			if (w == end)
			{
				isend = true;
				return;
			}
			dfs(w);
		}
	}
}

///找环,从beg到beg
void dfs(int v, int u)
{
	vis[v] = true;
	list<int>::iterator it;
	for (it = point[v].begin(); it != point[v].end(); ++it)
	{
		if (hascycle)
			return;
		int w = (int) * it;
		if (!vis[w])
		{
			edgeTo[w] = v;
			dfs(w, v);
		}
		else if (w != u && w == beg)
			///该已找到的点不是前一个点(上一层dfs的点)
			///说明从该点出发可以沿着另一条路回来,所以G有环。
		{
			edgeTo[w] = v;
			hascycle = true;
			return;
		}
	}
}

///简单找环
void simpledfs(int v, int u)
{
	vis[v] = true;
	list<int>::iterator it;
	for (it = point[v].begin(); it != point[v].end(); ++it)
	{
		if (hascycle)
			return;
		int w = (int) * it;
		if (!vis[w])
			dfs(w, v);
		else if (w != u)
			///该已找到的点不是前一个点(上一层dfs的点)
			///说明从该点出发可以沿着另一条路回来,所以G有环。
		{
			hascycle = true;
			return;
		}
	}
}

///双色否
void colordfs(int v)
{
	vis[v] = true;
	list<int>::iterator it;
	for (it = point[v].begin(); it != point[v].end(); ++it)
	{
		if (!isTwoColorable)
			return;
		int w = (int) * it;
		if (!vis[w])
		{
			color[w] = !color[v];
			colordfs(w);
		}
		else if (color[w] == color[v])
		{
			isTwoColorable = false;
			return;
		}
	}
}

///找连通分量,遍历型
void exdfs(int v)
{
	vis[v] = true;
	cc[count].insert(v);
	list<int>::iterator it;
	for (it = point[v].begin(); it != point[v].end(); ++it)
	{
		int w = (int) * it;
		if (!vis[w])
			exdfs(w);
	}
}

///应用1
///输出起点v到终点w的路径,以空格隔开
///如果不存在,则输出-1
inline void printpath(int v, int w)
{
	memset(vis, 0, sizeof(vis));
	memset(edgeTo, -1, sizeof(edgeTo));
	isend = false;
	while (!path.empty())
		path.pop();
	if (v != w)
	{
		end = w;
		dfs(v);
		for (int x = w; x != v; x = edgeTo[x])///先从w到v
		{
			if (~edgeTo[x]) /// edgeTo[x] != -1
				path.push(x);
			else ///说明v,w在两个不同的连通分量上
			{
				printf("-1\n");
				return;
			}
		}
		printf("%d", v);
		while (!path.empty())
		{
			printf(" %d", path.top());
			path.pop();
		}
		printf("\n");
	}
	else///找一个环
	{
		hascycle = false;
		beg = v;
		dfs(v, v);
		if (hascycle)
		{
			for (int x = edgeTo[v] ; x != v; x = edgeTo[x])
				path.push(x);
			printf("%d", v);
			while (!path.empty())
			{
				printf(" %d", path.top());
				path.pop();
			}
			printf(" %d\n", v);
		}
		else
			printf("-1\n");
	}
}

///应用2
///判断是否为无环图(假设不存在自环或平行边)
inline void hasCycle(int n)
{
	memset(vis, 0, sizeof(vis));
	hascycle = false;
	for (int i = 0; i < n; ++i)
		if (!vis[i])
			simpledfs(i, i);
}

///应用3
///返回连通子图的个数
inline int count_connected_subgraph(int n)
{
	memset(vis, 0, sizeof(vis));
	for (int i = 1; i <= count; ++i)
		cc[i].clear();
	count = 1;
	for (int i = 0; i < n; ++i)
	{
		if (!vis[i])
		{
			exdfs(i);
			++count;
		}
	}
	return count - 1;
}

///应用4
///判断G是否为二分图
inline void checkTwoColor(int n)
{
    memset(vis, 0, sizeof(vis));
	memset(color, 0, sizeof(color));
	isTwoColorable = true;
	for (int i = 0; i < n; ++i)
		if (!vis[i])
			colordfs(i);
}

int main(void)
{
	int n, m, k, temp, v, w;///点数=n,边数=m,查询数=k
	while (~scanf("%d%d%d", &n, &m, &k))
	{
		///0. 初始化
		temp = m;
		while (temp--)
		{
			scanf("%d%d", &v, &w);///这里输入要求为0~(n-1)
			point[v].push_front(w);
			point[w].push_front(v);
		}

		///1. 判断图G是否有环
		hasCycle(n);
		printf(hascycle ? "YES\n" : "NO\n");

		///2. 判断图G是否为二分图
		checkTwoColor(n);
		printf(isTwoColorable ? "YES\n" : "NO\n");

		///3. 连通子图的个数及每个连通子图所包含的点(升序输出)
		printf("%d\n", count_connected_subgraph(n));
		for (int i = 1; i < count; ++i)
		{
			set<int>::iterator it;
			for (it = cc[i].begin(); it != cc[i].end(); ++it)
				printf("%d ", *it);
			printf("\n");
		}

		///4. 判断是否存在v到w的路径/求v到w的路径(保证v,w在范围内)
		while (k--)
		{
			scanf("%d%d", &v, &w);
			printpath(v, w);
		}

		///0. 初始化
		for (int i = 0; i < n; ++i)
			point[i].clear();
		printf("\n");
	}
	return 0;
}

待实现:欧拉回路
7月14日每日两题 阅读详情

相关推荐

解忧杂货铺(四):Hightec生成HEX方法+小功能开启

Hightec使用的一些常用技能

梦想技术家 2160

【算法】DFS模板

DFS的核心思想是循环嵌套,将一个大问题拆分成一个个相同小问题,然后将小问题(递归的每一轮)进行判断 模板 void dfs(int step) //步长 { if(/*跳出循环的条件*/){ return; //return十分关键,否则循环将会无法跳出 } /*函数主体 对功能进行实现*/ for(/*对现有条件进行罗列*/){ if(/*判断是否合理*/){ //将条件修改

Elephant_King的博客 4348

[捷稀 JCG Q30 Pro 刷机说明] 以刷入openwrt24.10为例

摘要: 本文详细介绍了捷稀JCG Q30 Pro路由器刷入OpenWrt 24.10系统的步骤。通过先刷入OpenWrt 23.05过渡固件,再升级Uboot,最后通过TFTP加载工厂镜像完成刷机。关键步骤包括解锁分区、刷写Uboot、进入恢复模式及配置网络。文章还提供了无线设置、Tailscale内网穿透等进阶命令,并附参考文档和固件下载链接。适用于有一定技术基础的玩家,需注意操作风险,严格按流程执行。

贤时间 7137

dfs模板

2022.1.10学习总结

夏日漱石的博客 1721

用LTspice仿真Buck电路输出电容:从参数计算到波形优化的全流程演示

本文详细介绍了使用LTspice仿真Buck电路输出电容的全流程,从理论计算到波形优化。通过解析关键参数如纹波电压、瞬态响应和ESR,结合工程计算方法和LTspice仿真技巧,帮助工程师优化Buck电路设计,解决输出纹波过大和瞬态响应不佳的问题。

night的博客 851

SAP PP模块MRP控制参数实战指南:从NETCH到NEUPL的深度解析

本文深入解析SAP PP模块中MRP控制参数的配置与应用,涵盖NETCH、NETPL和NEUPL三种运行模式的优化策略。通过实战案例和参数对比,帮助用户提升物料需求计划的效率和准确性,优化库存周转率和生产交付能力。

weixin_28419039的博客 244

宝岛探险

题目描述 小哼通过秘密方法得到一张不完整的钓鱼岛航拍地图。钓鱼岛由一个主岛和一些附属岛屿组成,小哼决定去钓鱼岛探险。下面这个10*10的二维矩阵就是钓鱼岛的航拍地图。图中数字表示海拔,0表示海洋,1~9都表示陆地。小哼的飞机将会降落在(6,8)处,现在需要计算出小哼降落所在岛的面积(即有多少个格子)。注意此处我们把与小哼降落点上下左右相链接的陆地均视为同一岛屿。 输入 多组输入n,m,x,y n<=100 m<=100 0<x<=n 0<y<=m 其后n*

qq_46048366的博客 326

杂货店商品数据集挖掘关联规则实验

(2)选择事务集中前100条事务,选择合适的支持度阈值,使用Apriori算法和FP-growth算法挖掘频繁项集(推荐使用mlxtend包的apriori和fpgrowth函数),并对比apriori算法和fpgrowth算法的时间复杂度;(比如用户1000在2015年3月15日对应的事务为{‘sausage’,’whole milk’,’semi-finished bread’,’yogurt’}),然后按照用户ID递增,时间递增的方式对事务进行排序;7. 排版工整自洽,图表标题准确(10分)

m0_62500122的博客 1441

深度优先算法 DFS总结(算法详解+模板+例题)

沿着树的深度遍历树的节点,尽可能深的搜索树的分支。共 m+1 行,第 1 行为 2 个数,n 和 m,分别表示一共有 n(n≤105) 篇文章(编号为 1 到 n)以及m(m≤106) 条参考文献引用关系。一个如下的 6×6 的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。有一个 n \times mn×m 的棋盘,在某个点 (x, y)(x,y) 上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步。

Alex_Fufu的博客 1万+

手把手教你用STM32的ADC读取PT100模块,实现高精度温度采集(附完整代码)

本文详细介绍了如何利用STM32的ADC模块读取PT100温度传感器信号,实现高精度温度采集系统。从硬件选型、ADC配置校准到温度计算算法和软件滤波技术,提供完整的实现方案和优化技巧,帮助工程师快速构建稳定可靠的温度监测系统。

weixin_29185199的博客 347

FastAPI 高级特性:同异步路由函数、依赖注入与后台任务

在现代 Web 开发中,高效的性能和简洁的代码结构是至关重要的。FastAPI 作为一个现代、快速(高性能)的 Web 框架,凭借其对异步编程的原生支持和直观的依赖注入系统,迅速成为开发者的热门选择。在本文中,将深入探讨 `FastAPI` 中的几个核心概念:同异步函数的区别、`Depends` 依赖以及后台任务。

qq_43629857的博客 203

DFS (深度优先搜索) 算法详解 + 模板 + 例题,这一篇就够了

俗称的“不撞南墙不回头算法”!!!在本篇文章中详细介绍了DFS算法的基本步骤,详解了包括,排列组合问题、n皇后问题、素数问题等DFS的基本例题,后续会不断补充例题!!!

Layman的博客 18万+

PCL 计算点云包围球【2025最新版】

包围球通常用于简单排斥,因为与球体相交的方程很简单,同样重要的是,旋转一个球体并不会改变其范围。因此,当包围球用于简单排斥时,如果球体中心是对象的原点,则可以忽略对象的方向。

点云侠的博客 2068

洛谷P1157 组合的输出(Python)

①dfs函数的写法可以作为排列组合的模版;②递归时,这一层的count是对上一层决策的判断,count和cur不是对应的,所以一定要做数组越界判断。t=O83AP1157 组合的输出https://www.luogu.com.cn/problem/P1157。

2301_78161072的博客 507

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

深度优先搜索DFS_图文详解_Java代码_leetcode刷题模板

一、参考链接 -注 本文仅用于个人学习,侵权删。 1、基础讲解 搜索思想——DFS & BFS(基础基础篇) 数据结构:图的遍历–深度优先、广度优先 2、套路模板 深度优先搜索模板 回溯算法解题套路框架 二、图文讲解 回溯算法解题套路框架 DFS 算法就是回溯算法 ,废话不多说,直接上回溯算法框架。解决一个回溯问题,实际上就是一个决策树的遍历过程。你只需要思考 3 个问题: 1、路径:也就是已经做出的选择。 2、选择列表:也就是你当前可以做的选择。 3、结束条件:也就是到达决策树

lightupworld的博客 1061

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

【深度优先搜索DFS】

文章目录概念模版:迷宫游戏模版:迷宫最短路径问题 概念 深度优先搜索按照深度优先的方式进行搜索,通俗地说就是“一条路走到黑”。注意,这里的搜索指的是一种穷举的方式,把所有可行的方案都列出来,不断去尝试,直到找到问题的解。 深度优先搜索和递归的区别是:深度优先搜索是一种算法,注重的是思想;而递归是一种基于编程语言的实现方式,也就是说递归是实现深度优先搜索的这个算法的手段。 模版:迷宫游戏 迷宫问题的解法就需要dfs。我们对上下左右四个方向,一个方向一个方向地尝试,如果沿着某个方向不能走到终点,我们就要原

m0_52427832的博客 3918

efm32 入门.pdf

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

[dfs]回溯,连通图,树上直径

"/":是x+y值固定。采用a[N]存行(a[1]代表第一行),b[N]存列,c[N]主对角线,d[N]副对角线。(2)对角线的占领规律:“\"主对角线是y-x是固定值,为了避免下标小于0,整体加上n。(1)不要采用a[N][N]这样的方式存棋盘,占领一行,列和斜线打标记会很麻烦。(2)直接用函数求全排列。(1)dfs求全排列。

2301_79896098的博客 415

算法模型从入门到起飞系列——深度优先遍历(DFS)

全网最优质算法博主,将复杂的算法简单化分解,深入浅出,领略算法之美。

冲击AI顶流!!! 1318

【DFS专题】深度优先搜索 “暴搜”优质题单推荐 10道题(C++ | 洛谷 | acwing)

题单 一、模板 [极为重要] 全排列DFS 组合型DFS 指数DFS 二、专题 烤鸡 (指数BFS) P1088 火星人 【全排列】 P1149 火彩棒 [预处理 ] P2036 PERKET P1135 奇怪的电梯 暴力 P1036 [NOIP2002 普及组] 选数 (组合) P1596 [USACO10OCT]Lake Counting S 【DFS求图的连通块】 八数码

Remember who you are! 3987

【算法模板】DFS秒杀模板—附练习题(阳光号启航)

オレはいつかこの一味にも负けない仲间を集めて、世界一の财宝を见つけて、绝対なってやる!海贼王に! ​ 总有一天,我会聚集一群不输给这些人的伙伴,并找到世界第一的财宝,我要当海贼王!!!

小宝的博客 2854

DFS 两种模板(python)蓝桥杯

python蓝桥杯,dfs

qq_61623487的博客 402

(dfs回溯--排列)leetcode全排列

【代码】(dfs回溯--排列)leetcode全排列。

2403_87140725的博客 241

广度优先搜索(BFS)和深度优先搜索(DFS)代码模板

广度优先搜索: 1、如果不需要确定当前遍历到了哪一层,BFS代码模板如下: while queue 不空: cur = queue.pop() for 节点 in cur的所有相邻节点: if 该节点有效且未访问过: queue.push(该节点) 2、如果要确定当前遍历到了哪一层,BFS模板如下: 这里增加了level表示当前遍历到二叉树中的哪一层了,也可以理解为在一个图中,现在已经走了多少步了。size表示在当前遍历层有多少个元素,也

blue_coffeei的博客 1718

算法模版:暴力搜索之DFS【沈七】

算法模版:暴力搜索之DFS前言基本概念算法思想模板 前言 唤我沈七就行。 又是拖更的两周~ 因为开学将至,学校竞赛班也要在开学前的月底来一场测试,所以我就加快了学习算法的进度,最近两周涉猎了DFS、BFS、背包DP、线性DP。也整理了不少笔记,很快就会陆续更新啦~ 今天带来的是骗分神器–DFS 基本概念 DFS:是Depth First Search的简称 ,即深度优先搜索算法: 是一种用于遍历或搜索树或图的算法。 沿着树的深度遍历树的节点,尽可能深的搜索树的分支。 当节点v的所在边都己被探寻过或者在搜寻时

只想和你一起进步 7519

深度优先搜索(DFS)

所谓的深度优先搜索,就是利用递归与回溯,每次都考虑“当前这一步该如何做”,即有在step步时怎么做,做完当前步后,通过递归,同样的步骤来考虑step+1步该怎么做。对于这道题,开始的时候,没注意到朋友可能不止一个,而我们应该找到从天使到与她用时最短的朋友的时间,就是正确答案,所以,其实天使的位置才算得上起点。对于每次的 选择,都是一次拓展,至于是否拓展成功,那就要看条件的判断啦。,当然啦,深度优先搜索,比较直接的可以用于二维走迷宫之类的题目,走的过程中,我们要注意是否越界,是否能继续走下去。

牛牛博士博客 125

深度优先搜索(DFS)(C++)

对于DFS的学习来说,刚开始是很难去理解的,但是通过画图可以很好的帮我们理解代码的实现过程,但是想彻底的弄懂DFS,必须去模拟一下DFS的实现过程,并且加以运用。刷题就是个不错的选择,对此我推荐几个常见的模板题供大家练习1.全排列。2.八皇后。3.组合问题。上面推荐的几个都是基础的DFS题目,如果想要更熟练的掌握DFS,可以自行去找一些题目。DFS算法是一种重要的算法,可以用于解决许多问题。在本篇博客中,我们介绍了如何使用C++实现DFS算法。希望这个例子能帮助你更好地理解和应用DFS算法。

weixin_72668830的博客 641
上一篇: HDU 1278 漂亮面料的设计(超级模拟)
下一篇: Codeforces VK Cup 2012 Qualification Round 1 / 158A Next Round(模拟)
synapse7
博客等级 码龄14年 432粉丝 701原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值