Gym - 101611C Carpet——树链剖分

版权声明:欢迎大家转载,转载请注明出处 https://blog.csdn.net/hao_zong_yin/article/details/82788506

根节点到每个节点经过的轻链总数不超过log(n),因此可以把轻链放在20上,把重链放在1e6上,同时用dfs序将节点分布开,就可以满足要求了,注意一下dfs的顺序,先遍历轻链再遍历重链,这样可以保证不交叉

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1e5 + 10;
int mem, head[maxn];
struct Edge { int to, next; }edges[maxn<<1];
void addedge(int from, int to) {
    edges[mem].to = to; edges[mem].next = head[from]; head[from] = mem++;
}
int sz[maxn], son[maxn];
int x[maxn], y[maxn], cnt;
void init() {
    mem = 0;
    memset(head, -1, sizeof(head));
    cnt = 0;
}
void dfs1(int f, int u) {
    sz[u] = 1;
    son[u] = -1;
    for (int i = head[u]; ~i; i = edges[i].next) {
        int v = edges[i].to;
        if (v == f) continue;
        dfs1(u, v);
        sz[u] += sz[v];
        if (son[u] == -1 || sz[v] > sz[son[u]]) son[u] = v;
    }
}
void dfs2(int f, int u, int d) {
    x[u] = ++cnt;
    y[u] = d;
    if (son[u] == -1) return;
    for (int i = head[u]; ~i; i = edges[i].next) {
        int v = edges[i].to;
        if (v == f || v == son[u]) continue;
        dfs2(u, v, d+1);
    }
    dfs2(u, son[u], d);
}
int main() {
    int n;
    scanf("%d", &n);
    init();
    for (int i = 1, u, v; i <= n-1; i++) {
        scanf("%d%d", &u, &v);
        addedge(u, v); addedge(v, u);
    }
    dfs1(0, 1);
    dfs2(0, 1, 1);
    for (int i = 1; i <= n; i++) printf("%d %d\n", x[i], y[i]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/hao_zong_yin/article/details/82788506