bzoj2815:[ZJOI2012]灾难

快被灭绝树灭绝了。

Pre

气死了,\(dnc\)数组初始为0就会是错的,初始为\(-1\)就是对的。

好像存在更新之后\(dnc[i]\)为0的情况。

求大佬教我为什么会有这种情况!!!

调了一个小时。

不过灭绝树还是可以。

Solution

对每一个点的儿子找他们重建树中的\(LCA\),在重建树中统计就是了。

Code

#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define xx first
#define yy second

using namespace std;

const int N = 500000 + 5;
int cd[N];
int n;
int top[N], rd[N], dnc[N];
queue<int> Q;
struct GR {
    int fr[N], to[N], h[N], tot, sz[N], fa[N][22], dep[N], deb;
    inline void add (int u, int v) {
        if (!deb) {
            swap (u, v);
            cd[v]++;
        }
        tot++;
        fr[tot] = h[u];
        to[tot] = v;
        h[u] = tot;
    }
    inline void update (int u, int v) {
        dep[u] = dep[v] + 1;
        fa[u][0] = v;
        for (int i = 1; i <= 19; ++i) {
            fa[u][i] = fa[fa[u][i - 1]][i - 1];
        }
    }
    inline int LCA (int u, int v) {
        if (dep[u] < dep[v]) {
            swap (u, v);
        }
        while (dep[u] != dep[v]) {
            for (int i = 19; i >= 0; --i) {
                if (dep[fa[u][i]] >= dep[v]) {
                    u = fa[u][i];
                }
            }
        }
        while (u != v) {
            for (int i = 19; i >= 0; --i) {
                if (fa[u][i] != fa[v][i]) {
                    u = fa[u][i];
                    v = fa[v][i];
                }
            }
            if (fa[u][0] == fa[v][0]) {
                u = fa[u][0];
                v = fa[v][0];
                break;
            }
        }
        return u;
    }
    inline void dfs () {
        while (Q.size ()) {
            Q.pop ();
        }
        for (int i = 1; i <= n; ++i) {
            if (!cd[i]) {
                Q.push (i);
            }
        }
        while (Q.size ()) {
            int tmp = Q.front ();
            if (tmp != n + 1) {
                sz[tmp] += 1;
            }
            Q.pop ();
            for (int i = h[tmp]; i; i = fr[i]) {
                int v = to[i];
                sz[v] += sz[tmp];
                /*if (v == 2330) {
                    printf ("%d %d %d %d\n", v, tmp, sz[v], sz[tmp]);
                }*/
                cd[v]--;
                if (!cd[v]) {
                    Q.push (v);
                }
            }
        }
    }
}x, y;

inline void Top ();

int main () {
    freopen ("testdata.in", "r", stdin);
    freopen ("testdata.out", "w", stdout);
    memset (dnc, -1, sizeof (dnc));
    x.deb = 1;
    scanf ("%d", &n);
    for (int i = 1; i <= n; ++i) {
        int tmp;
        while (1) {
            scanf ("%d", &tmp);
            if (!tmp) {
                break;
            }
            x.add (tmp, i);
            rd[i]++;
        }
    }
    Top();
    y.dfs ();
    for (int i = 1; i <= n; ++i) {
        printf ("%d\n", y.sz[i] - 1);
    }
    return 0;
}

inline void Top () {
    for (int i = 1; i <= n; ++i) {
        if (!rd[i]) {
            x.add (n + 1, i);
            rd[i]++;
        }
    }
    while (Q.size ()) {
        Q.pop ();
    }
    Q.push (n + 1);
    while (Q.size ()) {
        int tmp = Q.front();
        Q.pop();
        if (tmp != n + 1) {
            y.add (dnc[tmp], tmp);
            y.update (tmp, dnc[tmp]);
        }
        for (int i = x.h[tmp]; i; i = x.fr[i]) {
            int v = x.to[i];
            
            rd[v]--;
            if (!rd[v]) {
                Q.push(v);
            }
            
            if (dnc[v] < 0) {
                dnc[v] = tmp;
            }
            else {
                dnc[v] = y.LCA (dnc[v], tmp);
            }
        }
    }
}

Conclusion

这时重建一次树,总觉得会有重建\(n\)次树的题目,但是我没遇到过。

另外,论初始化的重要性。

猜你喜欢

转载自www.cnblogs.com/ChiTongZ/p/11142559.html