一个不错的深度优先搜索的题目

Posted 沙茶敏碎碎念

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一个不错的深度优先搜索的题目相关的知识,希望对你有一定的参考价值。

算法的本质不是背诵一个套路,而是去分析解决问题

题目:

一只来自南极的考古企鹅Q哥来到了北极,发现了一块石碑,上面记录着这样的故事:很久很久以前,有一个等级森严的企鹅王国,他们的社会关系可以抽象成一棵树。石碑还刻着一行字,上面写着每个人的上级如下面序列,接下来是一个长度为N的序列,每个元素都是一个数字。Q哥发现,这个序列好像有问题,因为按照这个序列画出来的不一定是一颗树,猜想有部分刻错了,现在给你一个序列,能否帮忙算出最少有多少个元素刻错了。

说明:


对于一颗这样的树,序列为[4,3,3,2],表示1的父节点是2,2的父节点是3,3的父节点是它本身3,4的父节点是2。

样例,序列上有4个元素,序列如下[2 3 3 4],那么最少有一处纰漏,一个合法的解是[2 3 4 4].如下图所示:


一个不错的深度优先搜索的题目

思考:

我们反过来进行思考,如果一个序列是合法的?那是长什么样子的呢?

1.最多只有一个点指向本身,那就是根节点

2.如果这些边是无向边,那么这N个点是连通的(两两可互相到达)


一个不错的深度优先搜索的题目

给定一个序列,我们把这个图画出来,如果分割成多部分,如果分割成多部分,我们需要将多个部分进行合并,我们有以下的策略:

1.找到一个自己指向自己的点,让它来做树根。(只有树根是自己指向自己的)

2.把图划分成多个连通块,将他们都指向树根

这里有一个隐藏的性质:对于每一个联通块,必然存在一个环 。怎么推导出这个性质呢?一个n个结点的树有n-1条边,那么再加上一个点必定存在环。

那么怎么找到一个联通块呢,这里我们使用深度优先搜索算法,DFS。在这个题目中,我们找到所有有自环的点,进行深度优先搜索,可以把整个联通块找出来。我们用sonNode[i][j]表示第i个结点,第j个儿子的编号是多少。代码如下(C++):




有没有可能存在没有自环边的联通块呢?有的!上图右上角就是另外一种情况,这种情况下,我们需要找到一条环边。怎么找呢?我们也是使用深度优先搜索,我们随便找这个环里面的任何一个结点,进行深度优先搜索,如果重新访问到一个已经访问的结点,那么就说明存在环了。下面是深度优先搜索的代码(C++)。



因为图中可能存在多个连通块,所以我们还需要遍历所有的结点,找到所有连通块的个数,下面是算法步骤。

1.找到一个没有访问的自环结点(父亲是他本身)

2.如果没有找到一个环边结点

3.遍历活获得整个连通块

4.判断是否所有结点都已经访问,否则执行1

好了,到此为止,我们把整个题目已经梳理出来了,如果有什么疑问,欢迎在评论区提问,如果你觉得我讲的不错,也可以关注我,后面会持续推出各类算法题。


以上是关于一个不错的深度优先搜索的题目的主要内容,如果未能解决你的问题,请参考以下文章

数据结构题目,广度优先和深度优先

深度优先搜索和广度优先搜索的深入讨论

一文搞懂深度优先搜索广度优先搜索(dfsbfs)

一文搞懂深度优先搜索广度优先搜索(dfsbfs)

深度优先搜索

搜索算法:深度优先搜索(DFS)