其他分享
首页 > 其他分享> > 树的直径,树形dp

树的直径,树形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