洛谷P5180 支配树

支配树

get了新技能。。名字真酷啊(逃

贴个板子

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define full(a, b) memset(a, b, sizeof a)
using namespace std;
typedef long long ll;
inline int lowbit(int x){ return x & (-x); }
inline int read(){
    int 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();
    return w ? -X : X;
}
inline int gcd(int a, int b){ return a % b ? gcd(b, a % b) : b; }
inline int lcm(int a, int b){ return a / gcd(a, b) * b; }
template<typename T>
inline T max(T x, T y, T z){ return max(max(x, y), z); }
template<typename T>
inline T min(T x, T y, T z){ return min(min(x, y), z); }
template<typename A, typename B, typename C>
inline A fpow(A x, B p, C lyd){
    A ans = 1;
    for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd;
    return ans;
}
const int N = 300005;
int n, m, k, dfn[N], fa[N], pos[N], parent[N], val[N], sdom[N], idom[N], size[N];
struct Graph{
    int cnt = 0, head[N];
    struct Edge{ int v, next; } edge[N<<1];
    void link(int a, int b){
        edge[cnt].v = b, edge[cnt].next = head[a], head[a] = cnt ++;
    }
}a, b, c, d;

void dfs(int s){
    dfn[s] = ++k, pos[k] = s;
    for(int i = a.head[s]; i != -1; i = a.edge[i].next){
        int u = a.edge[i].v;
        if(!dfn[u]) fa[u] = s, dfs(u);
    }
}

int find(int s){
    if(s == parent[s]) return s;
    int tmp = find(parent[s]);
    if(dfn[sdom[val[parent[s]]]] < dfn[sdom[val[s]]]) val[s] = val[parent[s]];
    return parent[s] = tmp;
}

void tarjan(){
    for(int i = k; i > 1; i --){
        int s = pos[i];
        for(int j = b.head[s]; j != -1; j = b.edge[j].next){
            int u = b.edge[j].v;
            if(!dfn[u]) continue;
            find(u);
            if(dfn[sdom[val[u]]] < dfn[sdom[s]]) sdom[s] = sdom[val[u]];
        }
        c.link(sdom[s], s);
        parent[s] = fa[s], s = fa[s];
        for(int j = c.head[s]; j != -1; j = c.edge[j].next){
            int u = c.edge[j].v;
            find(u);
            if(sdom[val[u]] == s) idom[u] = s;
            else idom[u] = val[u];
        }
    }
    for(int i = 2; i <= k; i ++){
        int s = pos[i];
        if(idom[s] != sdom[s]) idom[s] = idom[idom[s]];
    }
}

void calc(int s){
    size[s] = 1;
    for(int i = d.head[s]; i != -1; i = d.edge[i].next){
        int u = d.edge[i].v;
        calc(u);
        size[s] += size[u];
    }
}

void solve(){
    dfs(1), tarjan();
    for(int i = 2; i <= n; i ++){
        if(idom[i]) d.link(idom[i], i);
    }
    calc(1);
}

int main(){

    n = read(), m = read();
    full(a.head, -1), full(b.head, -1), full(c.head, -1), full(d.head, -1);
    for(int i = 1; i <= n; i ++)
        parent[i] = sdom[i] = val[i] = i;
    for(int i = 0; i < m; i ++){
        int u = read(), v = read();
        a.link(u, v), b.link(v, u);
    }
    solve();
    for(int i = 1; i <= n; i ++){
        printf("%d", size[i]);
        if(i != n) printf(" ");
    }
    puts("");
    return 0;
}
原文地址:https://www.cnblogs.com/onionQAQ/p/10838885.html