其他分享
首页 > 其他分享> > 小白月赛22 B : 树上子链

小白月赛22 B : 树上子链

作者:互联网

B:树上子链

考察点 : 树的直径
坑点 :   long long, 是点权不是边权
         一个点也算一条链

析题得侃:

关于树的直径
这道题考察的是树的直径,最好用树形DP来写,具体解释详见上述博客,
这道题不友好的地方是把原先的边权搞成了点权,这就让人十分的头疼,
一头疼这道题就凉凉,哈哈,可能还是对这个知识点掌握的不够到位吧

Code :

#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>

#define INF 0x3f3f3f3f

using namespace std;

const int maxn = 1e5 + 10;

typedef long long LL;

int head[maxn],Next[maxn << 1],ver[maxn << 1];
LL vis[maxn],a[maxn],dist[maxn];

int n,tot = 0;

LL ans = -INF;

int main(void) {
    void add(int u,int v);
    void dp(int u);
    scanf("%d",&n);
    for(int i = 1; i <= n; i ++) {
        scanf("%lld",&a[i]);
                // 一个点也可以是一条链
                // 先取一个最大值
        ans = max(ans,a[i]);
    }
    int u,v;
    for(int i = 1; i < n; i ++) {
        scanf("%d%d",&u,&v);
                // 双向边
        add(u,v);
        add(v,u);
    }
    dp(1);
    cout << ans << endl;
    return 0;
}

void add(int u,int v) {
    ver[++ tot] = v,Next[tot] = head[u];
    head[u] = tot;
    return ;
}

void dp(int u) {
    LL mx = 0;
    vis[u] = 1;
        // 初始化
    dist[u] = a[u];
    for(int i = head[u]; i; i = Next[i]) {
        int y = ver[i];
        if(vis[y]) continue;
                // 向叶子节点进行递归
        dp(y);
                // 树的直径 = 最长链 + 次长链
        ans = max(ans,mx + a[u] + dist[y]);
                // 更新最长链(实际上是一个最大节点)
        mx = max(mx,dist[y]);
    }
        // 更新其父节点
    dist[u] += mx;
    return ;
}

标签:22,int,子链,long,这道题,maxn,小白月赛,include
来源: https://www.cnblogs.com/prjruckyone/p/12354191.html