树与图的深度优先遍历
深度优先遍历,就是把每个顶点的x上面对每个分支时,任意 选一条边走下去,执行递归,直至回溯之后,在考虑其他边的走向
通常在图与树中使用邻接表来存储
那么head为表头数组,ver edge就是用来存储权值和终点
自己理解的邻接表靠的是存储边的编号来存图,比较抽象,但是以此遍历编号,head存编号,头节点在e的编号,每个e再存上一条边,以此循环直至为0(有人喜欢设置为-1)。next存储的上一条边的编号,head存储以这个点开始的最后一个边编号
void dfs(int x)//遍历边
{
v[x]=1;
for(int i=head[x];i;i=next)//从最后一个开始知道第一个,每次向前一个获取编号
{
int y=edge[i].ver;//获取权值
dfs(y);
}
}
void add(int x,int y,int z)//存储边
{
tot++;//编号
e[tot].to=y;
edge[tot].ver=z;
edge[tot].next=head[x];//上一条边
head[x]=tot;//最后一条边
}
树与图的广度优先遍历
这种遍历我们已经很了解了,这种实现需要一种队列进行实现,在BFS中不断从队列中取队首x,对x的多条分支,沿着每条分支到达的下一个节点(也就是连边)插入队尾,重复执行过程直至队列为空
这个知识点我们早就了解,这里就不再详细介绍
BFS满足两端性和单调性
void bfs()
{
msmset(d,0,sizeof(d));
queue<int> q;
q.push(1);
d[1]=1;//记录层数
while(q.empty()==0)
{
int x=q.front();q.pop();
for(int i=head[x];i;i=next[i])
{
int y=edge[i].ver;
if(d[y]) continue;
d[y]=d[x]+1;//记录层数
q.push(y);//继续入队
}
}
}
时间戳
按照深搜的过程,按照每个节点第一次被访问的顺序,以此给n个节点进行标记,这个标记就叫做时间戳,记作dfn。怎么说是第一次,因为我们知道一个点不可能只会被访问1次,肯定会被回溯,所有我们留第一次的顺序
树的深度
树当然是有深度的,如果用手算直接使用log来求就好了
树中的个节点深度是一种自顶向下的统计信息,一开始我们知道根节点深度0,每个节点x的深度为d[x],那么他的子节点y的深度d[y]=d[x]+1,结合自顶向下这一条件就能求出来了
void dfs(int x)
{
v[x]=1;//标记已经访问
for(int i=head[x];i;i=next[i])
{
int y=edge[i].ver;
if(v[y]) continue;
d[y]=d[x]+1;//计算层数
dfs(y);
}
}
树的重心
也有许多的信息是自底向上进行统计的,比如每个节点x为根的子树大小
对于一个节点x,如果我们把它从树中删除,那么原来的一棵树可能会分成若干个不相连的部分,其中每一部分都是子树,设maxpart函数表示在删除节点x后产生的子树中,最大的一颗的大小,那么x就是重心
void dfs(int x)
{
v[x]=1;
size[x]=1;//假设子树的大小
int maxpart=0;//假设,预处理
for(int i=head[x];i;i=next[i])
{
int y=edge[i].ver;
if(v[y]) continue;
dfs(y);
size[x]+=size[y];
maxpart=max(maxpart,size[y]);//获取最大的子树
}
maxpart=max(maxpart,n-size[x]);//删除这个点最大值
if(maxpart<ans)//这里为什么记录小一点的?
//
{
ans=maxpart;//记录对应长度
pos=x;//记录重点
}
}
2021.5.9修改
双端队列BFS
在一张图中,边权可能是1或0,现在我们想从某个节点到另一个节点,怎么样才能使路径边权值和最大?
这只是一个例题,大部分题就是一个抽象形式,很多抽象问题都可以转成这个模型
双端队列(STL dequeue),就是说这种结构可以从队首入队可以从队尾出队
这道题让谁想都知道最短路径,但是我们要用的并不是它
那么使用双端队列怎么完成?
由于这是一张边权要么是0要么是1的图,我们可以通过双端队列广搜来计算,算法的整体框架与一般广搜类似,只是要在每个节点沿分支拓展的时候稍稍作改变,如果 这条分支边权为0,那么就在队首入队,否则是0的话就在队尾入队。这样我们就可以保证,任意时刻的双端队列中节点对应的距离值都有“两端性”和“单调性”,每个节点第一次访问,就能得到最短距离
其实我个人理解的就是说这个跟动态规划很像,在分支前面有两条路可选,然后用判断走哪一条
实际上在权值中并不一定全部都是0或1,只是分了两种情况,一种模型
就是说用优先队列(优先堆)+BFS,也就说当一个搜索图存在两种不同的代价,那么我们把小的代价存在优先队列的队首,那么大一点的就放在后面,那么不断地取当前最小代价进行拓展,这样最后就去到了最小代价
可是这种做法有点类似于贪心,我们只是保存了当前的局部最优解,这样显然不完美,当前的代价最优不是说全局最优;当前的代价最差不一定说全局最差。
深度优先与广度优先遍历在树与图中的应用
本文介绍了树与图的深度优先遍历和广度优先遍历,阐述了邻接表的存储方式。深度优先遍历通过递归沿着一条边走下去,而广度优先遍历则利用队列进行。此外,文章还提及了时间戳的概念,树的深度计算,树的重心定义,以及双端队列在寻找最短路径问题中的应用,强调了双端队列保持的‘两端性’和‘单调性’确保找到最短路径。
1万+

被折叠的 条评论
为什么被折叠?



