HDU5449 Robot Dog

Posted xunzhen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU5449 Robot Dog相关的知识,希望对你有一定的参考价值。

题目蓝链

Description

给你一棵树,经过一条边的时间为(1)。有(q)次询问,每次询问给定一条有若干个关键点的路径,你需要依次经过这些关键点。你会从路径的起点开始,每次随机选择一条与当前点直接相连的边走过去。问你走完这条路径的期望时间为多少

Solution

首先,本题有这样一个性质(在树上)

对于任意一条链((x, y)),我们在链上任意取一个点(k),均满足(dis(x, k) + dis(k, y) = dis(x, y)),其中(dis(x, y))表示(x)点到(y)的期望时间

我们可以任选一个点作为根,然后预处理出两个数组(up[i], down[i]),分别表示(i)号点到它父亲需要的期望时间以及(i)号点父亲到它所需要的期望时间

然后我们就可以维护(up)(down)的树上前缀和就可以求出任意一条路径的期望时间了

下面是一种比较简单的求出(up)(down)的方法,(size[i])表示以(i)为根的子树大小
[ up[i] = 2 cdot size[i] - 1 down[i] = 2 cdot (n - size[i]) - 1 ]
还有一种比较容易理解,但理解比较麻烦的办法 传送门

Code

#include <bits/stdc++.h>

using namespace std;

#define fst first
#define snd second
#define mp make_pair
#define squ(x) ((LL)(x) * (x))
#define debug(...) fprintf(stderr, __VA_ARGS__)

typedef long long LL;
typedef pair<int, int> pii;

template<typename T> inline bool chkmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; }
template<typename T> inline bool chkmin(T &a, const T &b) { return a > b ? a = b, 1 : 0; }

inline int read() {
    int sum = 0, fg = 1; char c = getchar();
    for (; !isdigit(c); c = getchar()) if (c == ‘-‘) fg = -1;
    for (; isdigit(c); c = getchar()) sum = (sum << 3) + (sum << 1) + (c ^ 0x30);
    return fg * sum;
}

const int maxn = 5e4 + 10;

vector<int> g[maxn];

int n, m, d[maxn], sz[maxn], fa[maxn][16];

inline void dfs(int now, int f) {
    sz[now] = 1, d[now] = d[f] + 1, fa[now][0] = f;
    for (int i = 1; i <= 15; i++) fa[now][i] = fa[fa[now][i - 1]][i - 1];
    for (int i = 0; i < g[now].size(); i++) {
        int son = g[now][i];
        if (son == f) continue;
        dfs(son, now);
        sz[now] += sz[son];
    }
}

LL up[maxn], dn[maxn];
inline void DFS(int now, int f) {
    up[now] = (sz[now] << 1) - 1, dn[now] = ((n - sz[now]) << 1) - 1;
    up[now] += up[f], dn[now] += dn[f];
    for (int i = 0; i < g[now].size(); i++) {
        int son = g[now][i];
        if (son == f) continue;
        DFS(son, now);
    }
}

inline int lca(int x, int y) {
    if (d[x] < d[y]) swap(x, y);
    for (int i = 15; ~i; i--)
        if (d[fa[x][i]] >= d[y]) x = fa[x][i];
    if (x == y) return x;
    for (int i = 15; ~i; i--)
        if (fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i];
    return fa[x][0];
}

inline LL dis(int x, int y) {
    int LCA = lca(x, y);
    return up[x] - up[LCA] + dn[y] - dn[LCA];
}

int main() {
    freopen("C.in", "r", stdin);
    freopen("C.out", "w", stdout);

    int T = read();
    while (T--) {
        n = read();
        for (int i = 1; i <= n; i++) g[i].clear();
        for (int i = 1; i < n; i++) {
            int x = read() + 1, y = read() + 1;
            g[x].push_back(y), g[y].push_back(x);
        }
        dfs(1, 0), DFS(1, 0);
        m = read();
        for (int i = 1; i <= m; i++) {
            LL ans = 0;
            int cnt = read(), lst = read() + 1;
            for (int j = 1; j <= cnt; j++) {
                int now = read() + 1;
                ans += dis(lst, now);
                lst = now;
            }
            printf("%lld.0000
", ans);
        }
        if (T) printf("
");
    }

    return 0;
}


以上是关于HDU5449 Robot Dog的主要内容,如果未能解决你的问题,请参考以下文章

HDU 5007 Post Robot

HDU 5007 Post Robot

hdu-1573 Robot Motion

HDU 1035 Robot Motion

HDU 4576 Robot(概率dp)

hdu 5673 Robot 卡特兰数+逆元