一个不错的深度优先搜索的题目
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
好了,到此为止,我们把整个题目已经梳理出来了,如果有什么疑问,欢迎在评论区提问,如果你觉得我讲的不错,也可以关注我,后面会持续推出各类算法题。
以上是关于一个不错的深度优先搜索的题目的主要内容,如果未能解决你的问题,请参考以下文章