树的直径,树形dp

有根树从根、无根树从任意一个节点开始处理即可

1、不考虑边权,考虑路径中点的个数,可以从任意一个节点开始进行DFS,DFS返回以当前节点为根的子树中,以当前节点为端点的最长路径。

经过当前节点的最长路径,即为以当前节点的子节点为端点的前2长的路径长度的和+1,并以此更新全局最长路径(直径)。

2、边权任意大小,可以从任意一个节点开始进行DFS,DFS返回以当前节点的子树中,以当前节点为端点的最长路径。

经过当前节点的最长路径,可以先处理出以当前节点为端点的所有路径(DFS结果+边权)。

将前2长的路径(注意与0比较)求和即为经过当前节点的最长路径,并更新全局最长路径。

(AcWing算法提高课 1.7 树形DP)

AcWing 1072. 树的最长路径

复制代码
#include<bits/stdc++.h>

using namespace std;
vector<int> adj[10010];
vector<int> w[10010];
bool vis[10010];
int dis=0;
int DFS(int node)
{
    vis[node]=true;
    vector<int> nxt_road;
    for(int i=0;i<adj[node].size();i++)
    {
        if(!vis[adj[node][i]])
        {
            nxt_road.push_back(DFS(adj[node][i])+w[node][i]);
            
        }
        
    }
    sort(nxt_road.rbegin(),nxt_road.rend());
    if(nxt_road.size()==0)
    {
        return 0;
    }
    else if(nxt_road.size()==1)
    {
        dis=max(dis,max(0,nxt_road[0]));
        return max(0,nxt_road[0]);
    }
    else
    {
        dis=max(dis,max(0,nxt_road[0])+max(0,nxt_road[1]));
        return max(0,nxt_road[0]);
    }
}
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<n;i++)
    {
        int a,b,c;
        cin>>a>>b>>c;
        adj[a].push_back(b);
        w[a].push_back(c);
        adj[b].push_back(a);
        w[b].push_back(c);
    }
    DFS(1);
    cout<<dis<<endl;
    
}
View Code
复制代码

 

3、边权为正,可以使用两次BFS:(AcWing算法提高课 1.7 树形DP)

(1)任取一点作为起点,找到距离此点距离最远的一点u(DFS\BFS,推荐BFS),此时可以证明,u为某一直径的起点;

(2)以u作为起点,找到距离u最远的一点v(推荐BFS),此时uv路的长度即为直径。

复制代码
#include<bits/stdc++.h>

using namespace std;
vector<int> adj[10010];
vector<int> w[10010];
bool vis[10010];
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<n;i++)
    {
        int a,b,c;
        cin>>a>>b>>c;
        adj[a].push_back(b);
        w[a].push_back(c);
        adj[b].push_back(a);
        w[b].push_back(c);
    }
    queue<pair<int,int>> que;
    int last=-1;
    int dis=-1e9;
    que.push({1,0});
    
    while(que.size())
    {
        auto cur=que.front();
        que.pop();
        vis[cur.first]=true;
        if(cur.second>dis)
        {
            last=cur.first;
            dis=cur.second;
        }
        for(int i=0;i<adj[cur.first].size();i++)
        {
            auto nxt=adj[cur.first][i];
            if(!vis[nxt])
            {
                que.push({nxt,cur.second+w[cur.first][i]});
            }
        }
    }
    memset(vis,0,sizeof(vis));
    

    que.push({last,0});
    last=-1;
    dis=-1e9;
    while(que.size())
    {
        auto cur=que.front();
        que.pop();
        vis[cur.first]=true;
        if(cur.second>dis)
        {
            last=cur.first;
            dis=cur.second;
        }
        for(int i=0;i<adj[cur.first].size();i++)
        {
            auto nxt=adj[cur.first][i];
            if(!vis[nxt])
            {
                que.push({nxt,cur.second+w[cur.first][i]});
            }
        }
    }
    cout<<dis<<endl;
}
View Code
复制代码

 

posted @   80k  阅读(28)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
点击右上角即可分享
微信分享提示