ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

树的直径,树形dp

2022-06-16 12:02:28  阅读:147  来源: 互联网

标签:int 路径 back DFS 树形 push 直径 节点 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

 

标签:int,路径,back,DFS,树形,push,直径,节点,dp
来源: https://www.cnblogs.com/ydUESTC/p/16381471.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有