D47【模板】树的直径 B4016 树的直径

D47 树的直径 B4016 树的直径_哔哩哔哩_bilibili

B4016 树的直径 - 洛谷

方法1:两次DFS,仅正边权,能记录路径

方法2:树形DP,正负边权,不能记录路径

// 树的直径 正边权 两次DFS O(n)
#include<bits/stdc++.h>
using namespace std;

const int N=100005;
int n,rt,d[N];
vector<pair<int,int>> e[N];

void dfs(int u,int fa){
  if(d[rt]<d[u]) rt=u; //记录最远点
  for(auto [v,w]:e[u]){
    if(v==fa) continue;
    d[v]=d[u]+w; //d[v]从根走到v的距离
    dfs(v,u);
  }
}
int main(){
  cin>>n;
  for(int i=1,x,y;i<n;i++){
    cin>>x>>y;
    e[x].emplace_back(y,1);
    e[y].emplace_back(x,1);
  }
  dfs(1,0);  //找出离1最远的点rt
  d[rt]=0;
  dfs(rt,0); //找出离rt最远的点
  cout<<d[rt];
}

 

// 树的直径 正负边权 树形DP O(n)
#include<bits/stdc++.h>
using namespace std;

const int N=100005;
int n,md,f[N],g[N]; //f[u]/g[u] 从u向下走的最长/次长距离
vector<pair<int,int>> e[N];

void dfs(int u,int fa){
  for(auto [v,w]:e[u]){
    if(v==fa) continue;
    dfs(v,u);
    if(f[u]<f[v]+w) g[u]=f[u],f[u]=f[v]+w;
    else if(g[u]<f[v]+w) g[u]=f[v]+w;
  }
  md=max(md,f[u]+g[u]);
}
int main(){
  cin>>n;
  for(int i=1,x,y;i<n;i++){
    cin>>x>>y;
    e[x].emplace_back(y,1);
    e[y].emplace_back(x,1);
  }
  dfs(1,0);
  cout<<md;
}

 

// 树的直径 正负边权 树形DP O(n)
#include<bits/stdc++.h>
using namespace std;

const int N=100005;
int n,mxd,d[N]; //d[u]从u点向下走的最长距离
vector<pair<int,int>> e[N];

void dfs(int u,int fa){
  for(auto [v,w]:e[u]){
    if(v==fa) continue;
    dfs(v,u);
    mxd=max(mxd,d[u]+w+d[v]); //拼凑直径
    d[u]=max(d[u],d[v]+w);    //更新d[u]
  }
}
int main(){
  cin>>n;
  for(int i=1,x,y;i<n;i++){
    cin>>x>>y;
    e[x].emplace_back(y,1);
    e[y].emplace_back(x,1);
  }
  dfs(1,0);
  cout<<mxd;
}

  

树的直径 - OI Wiki

 

posted @ 2024-09-07 07:06  董晓  阅读(534)  评论(0)    收藏  举报