L2-043 龙龙送外卖

龙龙是“饱了呀”外卖软件的注册骑手,负责送帕特小区的外卖。帕特小区的构造非常特别,都是双向道路且没有构成环 —— 你可以简单地认为小区的路构成了一棵树,根结点是外卖站,树上的结点就是要送餐的地址。

每到中午 12 点,帕特小区就进入了点餐高峰。一开始,只有一两个地方点外卖,龙龙简单就送好了;但随着大数据的分析,龙龙被派了更多的单子,也就送得越来越累……

看着一大堆订单,龙龙想知道,从外卖站出发,访问所有点了外卖的地方至少一次(这样才能把外卖送到)所需的最短路程的距离到底是多少?每次新增一个点外卖的地址,他就想估算一遍整体工作量,这样他就可以搞明白新增一个地址给他带来了多少负担。

输入格式:

输入第一行是两个数 N 和 M (2≤N≤105, 1≤M≤105),分别对应树上节点的个数(包括外卖站),以及新增的送餐地址的个数。

接下来首先是一行 N 个数,第 i 个数表示第 i 个点的双亲节点的编号。节点编号从 1 到 N,外卖站的双亲编号定义为 −1。

接下来有 M 行,每行给出一个新增的送餐地点的编号 Xi​。保证送餐地点中不会有外卖站,但地点有可能会重复。

为了方便计算,我们可以假设龙龙一开始一个地址的外卖都不用送,两个相邻的地点之间的路径长度统一设为 1,且从外卖站出发可以访问到所有地点。

注意:所有送餐地址可以按任意顺序访问,且完成送餐后无需返回外卖站

输出格式:

对于每个新增的地点,在一行内输出题目需要求的最短路程的距离。

输入样例:

7 4
-1 1 1 1 2 2 3
5
6
2
4

输出样例:

2
4
4
6

思路:首先这是树。考虑走一遍在回到原点怎么算?不用回到原点只需要减去离根节点最远的点。

要走到5,就需要把2也走了,此时走一圈为4,不会到原点为2

加上6,6到已有节点的最短路径为6->2长度为1, 走一圈的最小值为4 + 1 * 2 = 6,不回到原点就为6 - 2(距离原点最长的距离) = 4

坑点:题没说点1一定是跟节点啊

递归求高度

#include<iostream>

using  namespace std;

const int N  = 1e5 + 10;

int n, m, root;
int t[N], f[N], h[N];
int ans;

int cntt(int x){
    if(h[x])    return h[x];
    h[x] = cntt(t[x]) + 1;
    return h[x];
}

void add(int x){
    if(f[x]) return;
    ans += 2;
    f[x] = 1;
    add(t[x]);
}

int main(){
    cin >> n >> m;
    for(int i=1; i<=n; i++) {
        cin >> t[i];
        if(t[i]==-1) 
            root = i;    
    }

    h[root] = 1;
    for (int i = 1; i<=n; i++){
        if(h[i]==0){
            cntt(i);
        }
    }

    int maxh = 1, k;
    f[root] = 1;
    while(m--){
        cin >> k;
        maxh = max(maxh, h[k]);
        add(k);
        cout << ans - maxh + 1 << endl;
    }

    return 0;
}

bfs求高度

#include<iostream>
#include<vector>

using  namespace std;

const int N  = 2e5 + 10;

int n, m, root;
int t[N], f[N], h[N];//父节点, 已访问的点, 高度
int ans, q[2 * N];
vector<int> son[N];//子节点

void bfs(){
    h[root] = 1;
    int ff, rr, t;
    ff = rr = 0;
    q[rr++] = root;
    while(ff<rr){
        t = q[ff++];
        for(auto i : son[t]){
            q[rr++] = i;
            h[i] = h[t] + 1;
        }
    }
}

void add(int x){
    if(f[x]) return;
    ans += 2;
    f[x] = 1;
    add(t[x]);
}

int main(){
    cin >> n >> m;
    for(int i=1; i<=n; i++){ 
        cin >> t[i];
        if(t[i]!=-1)
            son[t[i]].push_back(i);
        else root = i;
    }
    
    bfs();//bfs统计每个节点的高度

    int maxh = 1, k;
    f[root] = 1;
    while(m--){
        cin >> k;
        maxh = max(maxh, h[k]);
        add(k);
        cout << ans - maxh + 1 << endl;
    }
    return 0;
}

本文作者:TTMoon

本文链接:https://www.cnblogs.com/shen75/p/16198804.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   TTMoon  阅读(120)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
🔑