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