小白月赛6-C 树的最长路径 (dp) ʕ •ᴥ•ʔ

桃花一簇开无主,可爱深红映浅红。

                                        ——《题百叶桃花》

    桃花长在桃树上,树的每个节点有一个桃花,调皮的HtBest想摘尽可能多的桃花。HtBest有一个魔法棒,摘到树上任意一条链上的所有桃花,由于HtBest法力有限,只能使用一次魔法棒,请求出Htbest最多可以摘到多少个桃花。

输入描述:

第一行有一个正整数n,表示桃树的节点个数。
接下来n-1行,第i行两个正整数ai,bi ,表示桃树上的节点ai,bi之间有一条边。

输出描述:

第一行一个整数,表示HtBest使用一次魔法棒最多可以摘到多少桃花。

示例1

输入

复制

3
1 2
2 3

输出

复制

3

示例2

输入

复制

3
1 2
1 3

输出

复制

3

示例3

输入

复制

4
1 2
2 3
3 4

输出

复制

4

这道题一道非常经典的树的最长路径的题,需要用到 vector 来存

f1 f2 为最长边和次长边 什么是f1,f2相加呢? 看下图

 它是以 1 为出发点 我们要求的是树最长直径 那么应该是左子树+右子树 这样求得才是总得结果 为什么还要+1 是因为没有本身

解释一下核心代码吧:

void dfs(int u,int per)
{

    //用1-2-3-4举例  当一直跑到4这个点的时候
    int k=g[u].size();// k=1;
    for(int i=0;i<k;i++)
    {
        if(g[u][i]==per)//3 = 3 推出
        continue;
        dfs(g[u][i],u);//(4,3)//(3,2)
        if(f1[g[u][i]]+1>=f1[u])//f1[4]+1>=f1[3]
        {
            f2[u]=f1[u];//f2[3]=f1[3]=0;
            f1[u]=f1[g[u][i]]+1;//f1[3]=f1[4]+1;
        }
        else
        {
            f2[u]=max(f1[g[u][i]+1]+1,f2);
        }
    }
    ans=max(ans,f1[u]+f2[u]+1);//ans=1
}

然后就是递推了 应该好理解一些

#include <cstring>
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <string.h>
#include <vector>
#define ll long long
#define pi acos(-1.0)
using namespace std;
vector<int>g[1000010];
int ans=0;
int f1[1000010],f2[1000010];
void dfs(int u,int per)
{
	int k=g[u].size();
	for(int i=0;i<k;i++)
	{
		if(g[u][i]==per)//当子节点和父节点 相同时跳出  
		continue;
		dfs(g[u][i],u);
		if(f1[g[u][i]]+1>=f1[u])
		{
			f2[u]=f1[u];
			f1[u]=f1[g[u][i]]+1;
		}
		else 
		{
			f2[u]=max(f1[g[u][i]+1]+1,f2);
		}
	}
	ans=max(ans,f1[u]+f2[u]+1);
	
}
int main()
{
	
	int t;
	scanf("%d",&t);
	for(int i=1;i<t;i++)
	{
		int a,b;
		scanf("%d%d",&a,&b);
		g[a].push_back(b);// 因为它是一个无向图 所以需要两边都存
		//举例:如果它输入 2,1 3,1  
		g[b].push_back(a);
	} 
	dfs(1,0);// 0 为父节点,1为子节点 
	printf("%d\n",ans);
}

猜你喜欢

转载自blog.csdn.net/henucm/article/details/81841473