图论入门——树的深度(Graph Theory——depth)

什么是图论?

在c++中,有一个非常重要的理论,即为图论(Graph Theory),是数论的一个分支图论是一个较为抽象的概念,所以理解起来会更加方便。一般图论都是有图和文字结合的,所以叫图论。

什么是树?

树是图论中的一个比较常见的点,我们平常所知的二叉树就是其中一种,其中还有三叉树和多叉树等等。在树中,没有子节点的叫做叶节点,从一个叶节点到根的距离的最大值即为这棵树的深度。

图论入门——树的深度(Graph Theory——depth)_第1张图片

如何求树的深度?

当我们在求树的深度时,我们有三种方法,让我们逐一对他们进行讲解。

1.递归算法

我们在遍历树的深度时,可以从根开始从上往下遍历,对于每一个节点,用递归向下遍历,具体代码如下:

#include
using namespace std;
int a[maxn];
int b[maxn][maxn];
int c[maxn]//每一个点的子节点数;
int ret=0;
void check(int p,int q)
{
	if(c[p]==0)
	{
		ret=max(ret,q);
        return ;
	}
	for(int i=0; i

2.遍历(朴素版)

如果我们从下往上遍历,那就要用子节点来保存父节点,可以少开一个一个维度,空间上是变小了的。

代码:

#include
using namespace std;
int a[maxn];
int b[maxn];
int main(){
    int n;
    scanf("%d",&n);
    for(int i=1; i<=n; i++)
    {
    	scanf("%d",&a[i]);
    	b[i+1]=a[i];//这里用子节点来指向父节点
	}
	int ret=0;
	for(int i=n; i>=1; i--)//从下往上遍历
	{
		int res=1;
		int ii=i;
		while(b[ii]!=0)//枚举遍历
		{
			ii=b[ii];
			res++;
		}
		ret=max(ret,res);
	}
	printf("%d",ret);
    return 0;
}

3.遍历(进阶版)

进阶版对于朴素版时间复杂度降低了,其基本含义是用一个数组保存每个节点的深度,这样就可以缩短时间,有点类似dp(动态规划)。

代码:

#include
using namespace std;
int a[maxn];
int b[maxn];
int c[maxn];
int main(){
    int n;
    scanf("%d",&n);
    for(int i=1; i<=n; i++)
    {
    	scanf("%d",&a[i]);
    	b[i+1]=a[i];
	}
	int ret=0;
	for(int i=n; i>=1; i--)
	{
		int res=1;
		int ii=i;
		while(b[ii]!=0)
		{
			if(c[b[ii]]>0)//判断是否有已知深度
			{
				res+=c[b[ii]];
				break;
			}
			ii=b[ii];
			res++;
		}
		ret=max(ret,res);
		c[i]=res;//记录深度
	}
	printf("%d",ret);
    return 0;
}

虽然时间上和递归一样,但是空间降低了。

总结

在图论中,树的深度不仅在机试中会出现,笔试中亦会提到,所以要好好看,好好学,wind在此祝大家早点拿到省一!

敬请期待下一篇《图论入门——连通块的个数》

你可能感兴趣的:(图论)