dfs

6.4.4 用 dfs 求欧拉回路 (UVa 10129)

我的未来我决定 提交于 2020-01-23 14:13:59
欧拉回路:该回路遍历了一个图中所有的边,并且每条边只遍历一次。(一笔画) 欧拉路径:从起点开始到终点,遍历了图中所有的边,并且每条边只遍历一次。 度数:一个点连接了几条边。 入度和出度分别指:进入该点的边的数量,走出该点的边的数量。 连通无向图存在欧拉回路的充要条件:所有点的度数都为偶数。 连通无向图存在欧拉路径的充要条件:仅存在两个度数为奇数的点,其他点的度数都为偶数。(这两个度数为奇数的点,一个为奇数,一个为偶数) 连通有向图存在欧拉回路的充要条件:对于所有的点,入度等于出度。 连通有向图存在欧拉路径的充要条件: 仅存在两个点,其中一个点的入度比出度大一,另一个店的出度比入度大一。(出度大的为起点,入度大的为终点) 根据连通性和度数可判断出无向图和有向图是否存在欧拉回路和欧拉路径,可用 dfs 构造欧拉回路和欧拉路径。 基本思路:使用 dfs 的方式,遍历图中所有的点。dfs 一个环,然后在回溯的过程中,可能会遇到一个公共点连接着另一个环,此时再对这个公共点进行 dfs 遍历另一个环…… 如此递归。在 dfs 完与 u 结点相连的 v 结点后,再将 u,v 这条边压入输出栈(采用逆序的顺序输出结果,因为 dfs 栈帧入栈的顺序与出栈的顺序相反,起始点最后才出栈)。 例如:用 dfs 求该图的欧拉路径 dfs 遍历该图的顺序为: (1, 2) (2, 3) (3, 4) (4,

POJ 2386 Lake Counting(DFS)

ぐ巨炮叔叔 提交于 2020-01-23 14:13:44
题意:有一个大小为N×M的园子,雨后积起了水。八连通的积水被认为是连在一起的。求园子里一共有多少水洼? * * * * W* (八连通指的就是左图中相对W的*的部分) * * * Sample Input 10 12 W........WW. .WWW.....WWW ....WW...WW. .........WW. .........W.. ..W......W.. .W.W.....WW. W.W.W.....W. .W.W......W. ..W.......W. Sample Output 3PS:样例中的3个水洼分别是在左上,左下,和右方。这是的一道入门的深度优先搜索题,很简单~~从任意的W开始,不停地把邻接的部分(八连通)用'.'代替。1次DFS后与初始的这个W连接的所有W就都被替换成了'.',因此直到图中不在存在W为止,总共进行DFS的次数就是答案了。8个方向的共对应了8种状态转移,每个格子作为DFS的参数至多被调用一次,所以复杂度为O(8×M×N)=O(M×N)。 #include<iostream> #include<algorithm> using namespace std; char field[105][105]; int N,M; void dfs(int x, int y) { //现在的位置(x,y) field[x][y] = '.';/

水池数目(DFS)

余生长醉 提交于 2020-01-23 14:13:02
水池数目 时间限制: 3000 ms | 内存限制: 65535 KB 难度: 4 描述 南阳理工学院校园里有一些小河和一些湖泊,现在,我们把它们通一看成水池,假设有一张我们学校的某处的地图,这个地图上仅标识了此处是否是水池,现在,你的任务来了,请用计算机算出该地图中共有几个水池。 输入 第一行输入一个整数N,表示共有N组测试数据 每一组数据都是先输入该地图的行数m(0<m<100)与列数n(0<n<100),然后,输入接下来的m行每行输入n个数,表示此处有水还是没水(1表示此处是水池,0表示此处是地面) 输出 输出该地图中水池的个数。 要注意,每个水池的旁边(上下左右四个位置)如果还是水池的话的话,它们可以看做是同一个水池。 样例输入 2 3 4 1 0 0 0 0 0 1 1 1 1 1 0 5 5 1 1 1 1 0 0 0 1 0 1 0 0 0 0 0 1 1 1 0 0 0 0 1 1 1 样例输出 2 3 思路:DFS深搜,第一个搜索题。。。 代码:#include<stdio.h> int pool[100][100],m,n; void DFS(int x,int y){ if(y>0&&x>0&y<=m&&x<=n&&pool[x][y]==1){ pool[x][y]=0; DFS(x-1,y); DFS(x,y-1); DFS(x+1,y); DFS(x,y

DFS【求连通块的数目】

北战南征 提交于 2020-01-23 14:12:19
标题: 细胞 标签: 搜索 详情: 一矩形阵列由数字0到9组成,数字1到9代表细胞,细胞的定义为沿细胞数字上下左右还是细胞数字则为同一细胞,求给定矩形阵列的细胞个数。如阵列: 02345000 67103456 05002045 60067100 00000089 有4个细胞 输入格式: 整数m,n(m行,n列)矩阵。 输出格式: 细胞的个数。 样例: 输入 4 10 0234500067 1034560500 2045600671 0000000089 输出 4 分析:对图中的每个细胞都遍历一遍,走过的标记为1。遇到未被标记的细胞则从这个细胞开始搜索,细胞数目增1。 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <vector> #include <set> #include <map> using namespace std; const int maxn=505; int m,n; int vis[maxn][maxn]; char a[maxn][maxn]; int cnt=0; int dir[4][2]={0,1,-1,0,0,-1,1,0};//四个方向 void dfs(int x,int y){

深度优先搜索DFS,求解部分和问题及poj2386水洼问题

别来无恙 提交于 2020-01-23 14:11:27
深度优先搜索(DFS)是搜索的手段之一。它从某个状态开始,不断地转移状态直到无法转移,然后回退到前一步的状态,继续转移到其他状态,如此不断重复,直至找到最终的解。 部分和问题: 给定整数a1、a2、...、an,判断是否可以从中选出若干数,使它们的和恰好为k。 分析: 从a1开始按顺序决定每个数加或不加,在全部n个数都决定后再判断它们的和是不是k即可。因为状态数是2 n+1 (每个数都有加和不加两种情况),所以复杂度是O(2 n )。 代码如下: /* 题目描述:能否找到数组a中的元素相加之和等于指定的数k 解决方法:深度优先搜索(dfs)对每个元素组合进行遍历 */ #include<iostream> using namespace std; int a[100],k,n; //已经从前i项得到了和sum,然后对于i项之后的进行分支 bool dfs(int i,int sum){ //如果前n项都计算过了,则返回sum是否与k相等 if(i==n) return sum == k; //不加上a[i]的情况 if(dfs(i+1,sum)) return true; //加上a[i]的情况 if(dfs(i+1,sum+a[i])) return true; //加不加a[i],都被无法与k相等,则返回false return false; } int main(){ cin

DFS-回溯与剪枝-C - N皇后问题

时光毁灭记忆、已成空白 提交于 2020-01-23 12:18:30
C - N皇后问题 在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。 你的任务是,对于给定的N,求出有多少种合法的放置方法。 Input共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。Output共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。Sample Input 1 8 5 0 Sample Output 1 92 10 1 #include <iostream> 2 #include <algorithm> 3 #include <cmath> 4 using namespace std; 5 6 int queen[12], q[12]={0}, N, sum=0; 7 8 int check(int n) { 9 for(int i=0; i<n; i++) 10 if(queen[i]==queen[n] || abs(queen[i]-queen[n])==abs(n-i)) 11 return 0; 12 return 1; 13 } 14 15 void DFS(int n) { 16 for(int i=0; i<N; i++){ 17 queen[n] = i; 18 if(check(n)){ 19 if(n == N-1)

网络流学习笔记

故事扮演 提交于 2020-01-23 07:26:30
网络流学习笔记: $ by~~wch $ 前言: 本文篇幅较长,结合右上角的目录了浏览会方便一些 然后本文主要还是自己复习所用,会偏向讲一些(博主经常忘的)核心,有些地方讲得粗略请谅解,所以大家可以对书看,书上都是大佬写的比较全面。(额,假定大家都有认真看书) 然后基本概念库里的知识比较多,实在接受不了直接往后看算法,博主尽量会在算法前标注需要的基本概念(或者直接讲),大家再回来挑着反复看就好。但是尽量要明白算法核心,只要懂了最大流的原理,这些基本概念会显得比较简单。另外带*号的可以忽略,博主也不会讲。 然后我们要有能学好网络流的信心,这个很重要! 一、基本概念库: 本文中弧和边是一个东西,然后大家要注意 容量 和 流量 是不同的两个概念; 残留容量和剩余流量是一个东西 ,但他们和 实际流量 要区分开来! 容量网络和网络最大流: 容量网络: 设 $ G(V, E) $ 是一个有向图, $ V $ 为点集, $ E $ 为边集,在 $ V $ 中有两个指定的特殊顶点: 源点 ( $ S $ )和 汇点 ( $ T $ )。每一条弧(边) $ <u, v>∈E $ ,都有一个给定权值 $ c(u, v) $ ,称为 弧的容量 。这样的有向网络 $ G $ 被称为容量网络。 弧的流量: 通过容量网络 $ G $ 中每条弧 $ <u, v> $ 上的 实际流量 (简称流量),记为 $ f

2019_GDUT_新生专题I选集 F POJ-1426

人盡茶涼 提交于 2020-01-22 22:35:57
题目: 给定一个正整数n,请编写一个程序来寻找n的一个非零的倍数m,这个m应当在十进制表示时每一位上只包含0或者1。你可以假定n不大于200且m不多于100位。 提示:本题采用Special Judge,你无需输出所有符合条件的m,你只需要输出任一符合条件的m即可。 Input 输入包含多组数据,每组数据仅一行,只包含一个正整数n (1 <= n <= 200). Output 对于输入的每组n,都输出任一符合条件的m。即使有多个符合条件的m,你也只需要输出一个即可。 Sample Input 2 6 19 0 Sample Output 10 100100100100100100 111111111111111111 做法:天坑,题目给定m的范围是100位,实际不超过19位,用long long即可直接保存,dfs参数有两个,一个是当前的m,一个是位数,发现m符合要求即输出并结束dfs,发现已经查找到了第20位也结束当前dfs。 代码: # include <iostream> # include <cstdio> # include <cstring> using namespace std ; int N , ans , n ; void dfs ( unsigned long long x , int k ) { if ( n && k <= 19 ) { if ( x %

树链剖分

风流意气都作罢 提交于 2020-01-22 20:25:17
重链剖分 概念: 重儿子:父亲结点的所有儿子中子树结点数目最多( \(size\) 最大)的结点 轻儿子:父亲结点中除了重儿子以外的儿子 重边:父亲结点和重儿子连成的边 轻边:父亲结点和轻儿子连成的边 重链:由多条重边连接而成的路径 轻链:由多条轻边连接而成的路径 性质: 在轻边 \((u,v)\) 中, \(size(u)/2 \geqslant size(v)\) 从根结点到任意一点的路径上,不超过 \(log\ n\) 条轻链和 \(log\ n\) 条重链 时间复杂度为 \(O(n\ log\ n)\) 先求出每个结点所在的子树大小,找到它的重儿子(即处理 \(siz\) 数组和 \(son\) 数组),记录其父亲以及深度(即处理 \(fa\) 数组和 \(de\) 数组) \(code\) : void dfs_son(int x,int fath) { siz[x]=1; fa[x]=fath; de[x]=de[fath]+1; for(int i=head[x];i;i=e[i].nxt) { int y=e[i].to; if(y==fath) continue; dfs_son(y,x); siz[x]+=siz[y]; if(siz[son[x]]<siz[y]) son[x]=y; } } 再将重儿子连接成重链,记录每个点所属重链的顶部端点(即处理 \

dfs简单应用(水坑数)

ぐ巨炮叔叔 提交于 2020-01-22 19:30:41
试题描述 有一个大小为MN的园子,雨后积起了水。八连通的积水被认为是连接在一起的。请求出园子里共有多少水洼?(八连通指的是下面图中相对W的的部分) 限制条件: N,M≤100 输入 第一行包含两个正整数 N 和 M,表示将一个园子地面分成N*M块方格,N 行,M列,接下来的 N 行描述了园子地面状况,其中‘W’表示积水的水洼,‘.’表示没有积水。 输出 仅一个数,表示水洼的总数。 输入示例 10 12 w…ww. .www…www …ww…ww. …ww. …w… …w…w… .w.w…ww. w.w.w…w. .w.w…w… …w…w. 输出示例 3 这道题的题目描述稍微有些绕弯。看懂之后发现,只要是连在一起的w,只能算作一个水坑,就是问没有连在一起的水坑数有多少 解题策略还是用dfs来实现 具体实现主要靠的是内外双层的遍历把每一个w都持续延展,知道没有与这块水坑相邻的w,返回主函数记录一个岛屿, # include <bits/stdc++.j> using namespace std ; void dfs ( int m , int n ) { a [ m ] [ n ] = . ; for ( int i = - 1 ; i <= - 1 ; i ++ ) ; for ( intj - = - 1 ; j <= 1 ; j ++ ) ; if ( m + i >= 0 &&