0
点赞
收藏
分享

微信扫一扫

luogu P5180 【模板】支配树

凶猛的小白兔 2022-02-15 阅读 47

https://www.luogu.com.cn/problem/P5180

这篇讲得好:https://www.luogu.com.cn/blog/Wankupi/solution-p5180

code:

#include<bits/stdc++.h>
#define N 400050
using namespace std;
vector<int> g[N], gr[N], gt[N];
int dfn[N], id[N], tot, Fa[N], semi[N], idom[N];
void dfs(int u) {
    dfn[u] = ++ tot;
    id[tot] = u;
    for(int v : g[u]) {
        if(dfn[v]) continue;
        Fa[v] = u; dfs(v);
    }
}

int fa[N], val[N];
int get(int x) {
    if(fa[x] == x) return x;
    int y = fa[x];
    fa[x] = get(fa[x]);
    if(dfn[semi[val[y]]] < dfn[semi[val[x]]]) val[x] = val[y];
    return fa[x];
}
void merge(int x, int y) {
    x = get(x), y = get(y);
    fa[y] = x;
}

int dmin(int x, int y) {
    return dfn[x] < dfn[y]? x : y;
}
int n, m, siz[N];
int main() {
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i ++) fa[i] = i, siz[i] = 1;
    for(int i = 1; i <= m; i ++) {
        int u, v;
        scanf("%d%d", &u, &v);
        g[u].push_back(v), gr[v].push_back(u);
    }

    dfs(1); dfn[0] = n + 1;

    for(int i = n; i >= 1; i --) {
        int u = id[i];
        for(int v : gr[u]) { // get semi
            if(dfn[v] < dfn[u]) semi[u] = dmin(semi[u], v);
            else {
                get(v);
                semi[u] = dmin(semi[u], semi[val[v]]);
            }
        }

        for(int v : gt[u]) {
            get(v);
            int x = val[v];
            if(dfn[u] == dfn[semi[x]]) idom[v] = u;
            else idom[v] = x;
        }

        val[u] = u;
        merge(Fa[u], u);
        gt[semi[u]].push_back(u);
    }

    for(int i = 2; i <= n; i ++) {
        int u = id[i];
        if(idom[u] != semi[u]) idom[u] = idom[idom[u]];
    }

    for(int i = n; i > 1; i --) {
        int u = id[i];
        siz[idom[u]] += siz[u];
    }
    for(int i = 1; i <= n; i ++) printf("%d ", siz[i]);
    return 0;
}
举报

相关推荐

0 条评论