【ccf-csp题解】第四次csp认证-第四题-网络延时-树的直径

题目描述

【ccf-csp题解】第四次csp认证-第四题-网络延时-树的直径_第1张图片

【ccf-csp题解】第四次csp认证-第四题-网络延时-树的直径_第2张图片

【ccf-csp题解】第四次csp认证-第四题-网络延时-树的直径_第3张图片

思路分析

本题所求的实际上是树的直径,即树中的任意两个结点之间的最大距离

采用的方法是dfs

从根节点开始遍历,对于每一个被dfs的结点m,返回此结点m到所有叶子结点的距离最大的那个即d1,同时在dfs过程当中记录结点m到所有叶子结点的距离第二大的那个,即d2

那么最终答案就是对于每一个结点取res=res(res,d1+d2)

举个栗子:

【ccf-csp题解】第四次csp认证-第四题-网络延时-树的直径_第4张图片

设最下面的1--4的编号分别为5,6,7,8

从1开始dfs,首先进入2,然后对2dfs,进入3,然后对3进行dfs,对3dfs的时候,又进入5,对5dfs,此时由于结点5没有分支,所以这一次dfs得到d1=d2=0,返回给结点3的值为d1+1=1,之后3也算dfs完毕,结果:d1=1,d2=0,返回给2的值为d1+1=2,然后开始对4dfs,此时会进入下一层,依次对6,7,8进行dfs均返回d1+1=1,所以对于4dfs的结果是d1=1,d2=1,返回给2的值为2,所以最终2dfs结果是d1=2,d2=2,此时得到ans最大值:d1+d2=4.返回给结点1的值为d1+1=3,所以对1dfs完毕得到的结果是d1=3,d2=0,最终返回的结果为d1+1=4,同时保留答案ans=4

最后再提示一下,虽然树的本质是无向图,但是在建立边的时候,直接建成从上往下指的有向边即可,因为dfs的时候是从上往下的。当然建立成无向边也可以,只不过需要一个bool数组标记已经遍历过的结点,防止进入无限循环。

满分代码

#include
#include
using namespace std;
const int N=20010;
int e[N],ne[N],h[N],idx;
int n,m;
int ans;
void add(int a,int b)
{
	e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
int dfs(int u)
{
	int d1=0,d2=0;
	for(int i=h[u];i!=-1;i=ne[i])
	{
		int j=e[i];
		int d=dfs(j);
		if(d>=d1)d2=d1,d1=d;
		else if(d>=d2)d2=d;
	}
	ans=max(ans,d1+d2);
	return d1+1;
}
int main()
{
	scanf("%d%d",&n,&m);
	memset(h,-1,sizeof h);
	for(int i=2;i<=n+m;i++)
	{
		int x;
		scanf("%d",&x);
		add(x,i);
	}
	dfs(1);
	cout<

你可能感兴趣的:(CCF-CSP,算法综合,算法,树的半径,ccf-csp,c++,图论)