返回题解分享
讨论 / 题解分享/ 帖子详情

景区导游(编程题) - 题解

#include <bits/stdc++.h>
#define int long long
using namespace std;

const int N = 1e5 + 10, M = 2 * N;
int h[N], e[M], ne[M], w[M] , idx;
int depth[N], fa[N][21];
int aa[N], dist[N];
int n, m;

void add(int a, int b, int c)
{
    e[++ idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx;
}


void bfs()
{
    memset(depth, 0x3f, sizeof depth);

    depth[0] = 0, depth[1] = 1;
    queue<int> q;
    q.push(1);

    while(q.size()){
        int t = q.front();
        q.pop();

        for(int i = h[t]; i; i = ne[i])
        {
            int j = e[i];
            if(depth[j] > depth[t] + 1)
            {
                depth[j] = depth[t] + 1;
                dist[j] = dist[t] + w[i];
                q.push(j);
                fa[j][0] = t;

                for(int k = 1; (1 << k) <= depth[j]; k ++ ) 
                    fa[j][k] = fa[fa[j][k - 1]][k - 1];
            }
        }
    }

}

int lca(int a, int b)
{
    // 当a在b上面是交换a,b
    if(depth[a] < depth[b]) swap(a, b);
    // 把a跳上来,直到a与b同层
    for(int k = 20; k >= 0; k -- )
        if(depth[fa[a][k]] >= depth[b]) // 从跳大层往跳小层试,一直到a,b同层
            a = fa[a][k]; // 当在不断接近b时,让a到接近后的节点上,再去跳更小层
            // 为了实现跳奇数层,即a肯定能跳到b同层或b下一层,取k = 0 后会跳到与b同层
            
    if(a == b) return a; // 如果相等,那b就是a和b的公共祖先
    
    for(int k = 20; k >= 0; k -- )
        if(fa[a][k] != fa[b][k]) // 记录a,b 最后不是同一个节点的各自的节点
        {
            a = fa[a][k];
            b = fa[b][k];
        }
        
    return fa[a][0]; // 看a,b再跳一层后的结果
}

int get_dist(int a, int b)
{
    return dist[aa[a]] + dist[aa[b]] - 2 * dist[lca(aa[a], aa[b])];
}

signed main()
{
    cin >> n >> m;
    memset(h, -1, sizeof h);

    for(int i = 1; i <= n - 1; i ++ ){
        int a, b, c;
        cin >> a >> b >> c;
        add(a, b, c), add(b, a, c);
    }

    bfs();
    int sum = 0;
    for(int i = 1; i <= m; i ++ )
    {
        cin >> aa[i];
        if(i > 1) sum += get_dist(i, i - 1);
    }

    for(int i = 1; i <= m; i ++ )
    {
        if(i == 1) cout << sum - get_dist(i, i + 1) << " ";
        else if(i == m) cout << sum - get_dist(i - 1, i) << endl;
        else cout << sum - get_dist(i - 1, i) - get_dist(i, i + 1) + get_dist(i - 1, i + 1) << " ";
    }
    return 0; 
}
0 回复 0 转发 0 喜欢 1 阅读
回复 (0)
默认 最新
暂无回复,快来抢沙发!