[长链剖分优化dp] BZOJ 3522/4543 Hotel

题目大意

给定一棵 \(n(n\leq 5000)\) 个点的树,求选出三个不同的点,使得三个点两两之间间距相等的方案数。

题解

\(f[u][j]\) 表示以 \(u\) 为根的子树中,到 \(u\) 距离为 \(j\) 的结点的数目,设 \(g[v][j]\) 表示lca在以 \(v\) 为根的子树中 ,且到 \(v\) 的距离相同,且 \(v\)\(u\) 的距离加 \(j\) 等于它们到 \(v\) 的距离的结点对数。

每访问到 \(u\) 的一个儿子 \(v\),就有

\[ans+=f[u][j]\times g[v][j+1]+f[v][j-1]\times g[u][j]\\ g[u][j+1]+=f[u][j+1]\times f[v][j]\\ g[u][j-1]+=g[v][j]\\ f[u][j]+=f[v][j-1] \]

时间复杂度 \(O(n^2)\)

Code

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

#define RG register int
#define LL long long

template<typename elemType>
inline void Read(elemType& T) {
    elemType X = 0, w = 0; char ch = 0;
    while (!isdigit(ch)) { w |= ch == '-';ch = getchar(); }
    while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
    T = (w ? -X : X);
}

struct Graph {
    struct edge { int Next, to; };
    edge G[10010];
    int head[5010];
    int cnt;

    Graph() :cnt(2) {}
    void clear(int n) {
        cnt = 2;fill(head, head + n + 2, 0);
    }
    void add_edge(int u, int v) {
        G[cnt].to = v;
        G[cnt].Next = head[u];
        head[u] = cnt++;
    }
};
Graph G;
int N;

int Height[5005];
LL f[5005][5005], g[5005][5005], ans;

void DFS(int u, int fa) {
    Height[u] = 0;
    f[u][0] = 1;
    for (int i = G.head[u];i;i = G.G[i].Next) {
        int v = G.G[i].to;
        if (v == fa) continue;
        DFS(v, u);
        Height[u] = max(Height[u], Height[v] + 1);
        for (int j = 0;j <= Height[u];++j)
            ans += f[u][j] * g[v][j + 1] + g[u][j] * f[v][j - 1];
        for (int j = 0;j <= Height[u];++j) {
            g[u][j + 1] += f[u][j + 1] * f[v][j];
            if (j >= 1) {
                g[u][j - 1] += g[v][j];
                f[u][j] += f[v][j - 1];
            }
        }
    }
}

int main() {
    Read(N);
    for (int i = 1;i <= N - 1;++i) {
        int u, v;
        Read(u);Read(v);
        G.add_edge(u, v);
        G.add_edge(v, u);
    }
    DFS(1, 0);
    printf("%lld\n", ans);

    return 0;
}

长链剖分优化dp

BZOJ 4543这道题 \(n\) 扩大到了 \(10^5\)

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

#define RG register int
#define LL long long

template<typename elemType>
inline void Read(elemType& T) {
    elemType X = 0, w = 0; char ch = 0;
    while (!isdigit(ch)) { w |= ch == '-';ch = getchar(); }
    while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
    T = (w ? -X : X);
}

const int maxn = 100005;

struct Graph {
    struct edge { int Next, to; };
    edge G[maxn << 1];
    int head[maxn];
    int cnt;

    Graph() :cnt(2) {}
    void clear(int n) {
        cnt = 2;fill(head, head + n + 2, 0);
    }
    void add_edge(int u, int v) {
        G[cnt].to = v;
        G[cnt].Next = head[u];
        head[u] = cnt++;
    }
};
Graph G;
int N;

int Height[maxn], Hson[maxn];
LL temp[maxn * 5], * f[maxn], * g[maxn], * id = temp, ans;

void DFS_Init(int u, int fa) {
    Height[u] = 1;
    for (int i = G.head[u];i;i = G.G[i].Next) {
        int v = G.G[i].to;
        if (v == fa) continue;
        DFS_Init(v, u);
        Height[u] = max(Height[u], Height[v] + 1);
        if (Height[v] > Height[Hson[u]]) Hson[u] = v;
    }
    return;
}

void DFS(int u, int fa) {
    if (Hson[u]) {
        f[Hson[u]] = f[u] + 1;
        g[Hson[u]] = g[u] - 1;
        DFS(Hson[u], u);
    }
    f[u][0] = 1;ans += g[u][0];
    for (int i = G.head[u];i;i = G.G[i].Next) {
        int v = G.G[i].to;
        if (v == fa || v == Hson[u]) continue;
        f[v] = id;id += Height[v] << 1;
        g[v] = id;id += Height[v] << 1;
        DFS(v, u);
        for (int j = 0;j < Height[v];++j) {
            if (j) ans += g[v][j] * f[u][j - 1];
            ans += g[u][j + 1] * f[v][j];
        }
        for (int j = 0;j < Height[v];++j) {
            g[u][j + 1] += f[u][j + 1] * f[v][j];
            if (j) g[u][j - 1] += g[v][j];
            f[u][j + 1] += f[v][j];
        }
    }
}

int main() {
    Read(N);
    for (int i = 1;i <= N - 1;++i) {
        int u, v;
        Read(u);Read(v);
        G.add_edge(u, v);
        G.add_edge(v, u);
    }
    DFS_Init(1, 0);
    f[1] = id;id += Height[1] << 1;
    g[1] = id;id += Height[1] << 1;
    DFS(1, 0);
    printf("%lld\n", ans);

    return 0;
}
posted @ 2021-03-30 20:38  AE酱  阅读(54)  评论(0编辑  收藏  举报