DFS问题的类型
一般看到连通块就是用DFS,不同的是需要用连通块的什么信息
如果问有多少个连通块?<=> 调用几次DFS,一般就是主函数里的dfs函数被调用的次数,在这个情况下,就需要对每个点属于哪个连通分量进行记录(用二维数组)
如果问一个连通块有多少块?<=> 做完一遍DFS有多少点被标记,可以做完一次DFS就可以知道,在DFS函数中,对访问过的点标记(用二维数组)
或者直接定义一个全局变量
以上两种标记只需要用一个二维数组,如果是有几个连通分量的话,只需要每次主函数调用DFS的时候,传一个数值作为这个连通分量的标记,这样DFS函数中,一个连通分量的点都用这个相同的数字标识;如果只需要记录一个连通分量有几个点,就直接记录0还是1即可
忽然想到的一些别的点:
1>.用while的时候,如果每次是一个新的case,那么while里面一定要先初始化
2>.if(m=n)把n的值赋给m,返回的是m的值,只要n不为0,那么就是true
DFS存图
一般用二维数组
一个二维数组存图的内容
一个二维数组存这个点是不是被访问过
怎么走遍所有点
如果是上下左右的话:
int dx[4]={0,0,-1,1};
int dy[4]={1,-1,0,0};
for(int i=0;i<4;i++)
{
x=x+dx[i];
y=y+dy[i];
}
如果是八个方向就对应再加上四个
主函数中调用d的DFS
声明全局变量
int idx[m][n];//记录点是都访问过的二维数组
int cnt;//连通分量的标记
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
{
if(idx[i][j]===0&&题目要求,什么样的点可以访问)
{
cnt++;
dfs(i,j,cnt);//在fds函数中,访问过的点就赋值cnt,表示属于同一个连通分量,连通分量的编号是cnt
}
}
DFS函数
void dfs(int r,int c,int id)//如果只是记录一个连通分量有几个点,不需要第三个参数
{
if(r<0||r>=m||c<0||c>=n) return;//首先判断这个点是不是超过图的边界了
if(idx[r][c]>0||不是可以走通的点) return ;//如果已经访问过,或者走不通
//如果上面两个条件都不是,说明这个点是连通分量中的点
标记上idx[r][c]=id;
for(int i=0;i<4;i++)
dfs(r+dx[i],c+dy[i],id);
}
BFS问题的类型
天然可以解决最短路的问题:(因为它首先走到的是一步可以走到的点)
每个点用结构体来定义:位置,和走到这个点的步数
BFS过程的实现上
一般定义结构体表示每个节点
是不是访问过,一般开一个数组存放,而不会放在BFS的结构体里面
初始点入队
判断队列不为空
{
出队一个点
遍历这个点的所有相邻的点,遍历的方法和DFS一样
,判断这些点是否可以走,把这些点要记录的内容算出
如果可以走,把这个点入队
}