首页 > 其他 > 详细

小白月赛22 B : 树上子链

时间:2020-02-23 22:35:21      阅读:135      评论:0      收藏:0      [点我收藏+]

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 B : 树上子链

原文:https://www.cnblogs.com/prjruckyone/p/12354191.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!