【模板】树的直径(dfs & dp)

树的直径

给定n个点 n-1条边 和每条边的val

输出直径的大小和 直径上的点的序号

input:
8
1 2 2
1 3 1
1 5 10
2 4 3
4 6 4
3 7 5
7 8 2

output:
19
6 4 2 1 5

法1.DFS

思路:跑两遍dfs 第一次求出一个端点c1,第二次求出第二个端点c2

第一次:任意一个点跑一遍dfs 记录最远的点为c1 ,二次:这个时候dist[c1]=0 从c1开始跑dfs

缺点:不能处理存在val为负数的情况

#include <cstdio>
#include <queue>
#include <deque>
#include <stack>
#include <map>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#define ep emplace_back 

#define lld long long 
#define ios std::ios::sync_with_stdio(false);std::cin.tie(0); 
#define vec vector 
const int N = 2e5+9;
const int INF = 0x7FFFFFFF; //2147483647

const int inf1 = 0x3f3f3f3f; //1061109567
const int inf2 = 0x7f7f7f7f; //2139062143 memset赋值用

using namespace std;


int c1,c2;//直径的两个端点
int c;//处理c1,c2用
int n;
int head[N],idx=0;
int dist[N];
int prenodes[N];
struct node{
    int to,val,next;
};
node e[N];
void add(int u,int v,int val){
    e[idx] = {v,val,head[u]};
    head[u] = idx++;
}
void bd(){
    cin>>n;
    memset(head,-1,sizeof head);
    for(int i=1 ; i<=n-1 ; ++i){
        int u,v,val;
        cin>>u>>v>>val;
        add(u,v,val);
        add(v,u,val);
    }
}
void dfs(int u,int fa,int tag){
    //tag==1才记录路径
    for(int i=head[u] ; i!=-1; i=e[i].next){
        int v = e[i].to;
        int val = e[i].val;
        if(v == fa) continue;
        dist[v] = dist[u] + val;
        if(tag==1)
            prenodes[v] = u;
        if(dist[v] > dist[c]) 
            c=v; 
        dfs(v,u,tag);
    }
}

int main(){
    ios;
    bd();
    dfs(1,0,0);
    c1=c;
    dist[c]=0;
    dfs(c,0,1);
    //记录第一个端点c1 = c 此时从c1开始 赋值dist[c1]=0;
    c2=c;
    cout<<dist[c]<<"\n";
    for(int i=c2 ; i!=0 ;i=prenodes[i]) cout<<i<<" ";
    return 0;
}

法2:树形的dp



#include <cstdio>
#include <queue>
#include <deque>
#include <stack>
#include <map>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#define ep emplace_back 

#define lld long long 
#define ios std::ios::sync_with_stdio(false);std::cin.tie(0); 
#define vec vector 
const int N = 2e5+9;
const int INF = 0x7FFFFFFF; //2147483647

const int inf1 = 0x3f3f3f3f; //1061109567
const int inf2 = 0x7f7f7f7f; //2139062143 memset赋值用

using namespace std;


int n, d = 0;
int dp[N];
vector<int> E[N];

void dfs(int u, int fa) {
  for (int v : E[u]) {
    if (v == fa) continue;
    dfs(v, u);
    d = max(d, dp[u] + dp[v] + 1);
    dp[u] = max(dp[u], dp[v] + 1);
  }
}

int main() {
  scanf("%d", &n);
  for (int i = 1; i <= n-1; i++) {
    int u, v;
    scanf("%d %d", &u, &v);
    E[u].push_back(v);
    E[v].push_back(u);
  }
  dfs(1, 0);
  printf("%d\n", d);
  return 0;
}

posted @ 2024-08-01 20:33  phrink  阅读(55)  评论(0)    收藏  举报