zoukankan      html  css  js  c++  java
  • 《P2597 [ZJOI2012]灾难》

    这里是个DAG,可以利用类似倍增的做法。

    但是可以直接支配树做,建立一个虚点向所有的起点,然后支配树就即可。

    // Author: levil
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int> pii;
    const int N = 2e5 + 5;
    const int M = 5e5 + 5;
    const LL Mod = 1e9 + 7;
    #define pi acos(-1)
    #define INF 1e16
    #define dbg(ax) cout << "now this num is " << ax << endl;
    
    int n,val[N],dfn[N],semi[N],idom[N],rk[N],fa[N],out[N],sz[N],tim = 0;
    vector<int> G[N],RG[N],T[N];
    namespace Node{
        int fa[N],val[N];
        void init() {
            for(int i = 1;i <= n + 1;++i) fa[i] = i;
        }
        int Find(int x) {
            if(x == fa[x]) return x;
            int ffa = fa[x];
            fa[x] = Find(fa[x]);
            if(dfn[semi[val[x]]] > dfn[semi[val[ffa]]]) val[x] = val[ffa];
            return ffa;
        }
        void Merge(int x,int y) {
            x = Find(x),y = Find(y);
            fa[y] = x;
        }
    };
    void dfs(int u) {
        dfn[u] = ++tim;
        rk[tim] = u;
        for(auto v : G[u]) {
            if(!dfn[v]) {
                fa[v] = u;
                dfs(v);
            }
        }
    }
    int getmin(int x,int y) {
        return dfn[x] < dfn[y] ? x : y;
    }
    void solve() {
        dfs(n + 1);
        dfn[0] = tim + 1;
        Node::init();
        for(int i = n + 1;i >= 1;--i) {
            int x = rk[i];
            for(auto v : RG[x]) {
                if(dfn[v] < dfn[x]) semi[x] = getmin(semi[x],v);
                else {
                    Node::Find(v);    
                    semi[x] = getmin(semi[x],semi[Node::val[v]]);
                }
            }
            for(auto v : T[x]) {
                Node::Find(v);
                int ma = Node::val[v];
                if(semi[ma] == x) idom[v] = x;
                else idom[v] = ma;
            }
            Node::val[x] = x;
            Node::Merge(fa[x],x);
            T[semi[x]].push_back(x);
        }
        for(int i = 2;i <= n + 1;++i) {
            int x = rk[i];
            if(idom[x] != semi[x]) idom[x] = idom[idom[x]];
        }
        for(int i = n + 1;i >= 2;--i) {
            int x = rk[i];
            ++sz[x];    
            if(idom[x]) sz[idom[x]] += sz[x];
        }
    }
    int main() {
        scanf("%d",&n);
        for(int i = 1;i <= n;++i) {
            int x;
            while(scanf("%d",&x),x != 0) {
                G[x].push_back(i);
                RG[i].push_back(x);
                out[i]++;
            }
        }
        for(int i = 1;i <= n;++i) {
            if(out[i] == 0) {
                G[n + 1].push_back(i);
                RG[i].push_back(n + 1);
            }
        }
        solve();
        for(int i = 1;i <= n;++i) printf("%d
    ",sz[i] - 1);
        system("pause");
        return 0;
    }
    View Code
  • 相关阅读:
    TreeSet类的排序问题
    TreeSet()详解
    css中vertical-align垂直居中的认识
    CSS3 float深入理解浮动资料整理
    层叠顺序与层叠上下文
    jquery.zclip轻量级复制失效问题
    文章转载利用border、transparent实现微风
    转载利用线性渐变实现晴天、多云特效
    转载利用伪元素单个颜色实现 hover 和 active 时的明暗变化效果
    MUI-最接近原生App体验的前端框架
  • 原文地址:https://www.cnblogs.com/zwjzwj/p/15154100.html
Copyright © 2011-2022 走看看