ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

支配树简记(不是教程)

2019-07-12 22:02:30  阅读:204  来源: 互联网

标签:sdom 教程 val int 支配 st 简记 dfn now


Pre

看了两天,终于看懂了(比\(\frac{1}{\infty}\)高阶的无穷小)\(\%\)。

Hints

1、初始化的三个数组要记住\(val.f.sdom\)。

2、\(find\)函数有一点神奇,之前没有见过,可以熟悉一下。

3、\(69\)~\(71\)行的代码,就是更新\(sdom\)的那一部分,考虑转移到\(sdom(x)\)。

当\(dfn(y)<dfn(x)\)

\(y\)还没有被访问并更新答案,因为我们是按照从大到小的顺序操作的,所以\(sdom(x)=y\)。

当\(dfn(y)>dfn(x)\)

\(y\)已经被更新,但是\(y\)的第二浅的老祖宗的\(dfn\)不会小于\(x\),最浅的老祖宗可以作为\(sdom(x)\)因为满足之间的点的\(dfn\)大于\(dfn(x)\),所以可以转移。

4、注意\(73\)行转移到\(tree\)的图里面。

5、\(83\)行,这是一个神奇的东西。因为\(idom(st.val(v))\)在这个时候时可能没有初始化的,为\(0\),又不能够在程序开始初始化,所以只有最后处理完了再来处理这个地方。

(开始的时候我以为我少考虑了几种情况,结果浪费了\(1\)个小时找推理错误,发现没有错)。

6、最重要的,大致思路要知道。

下面的代码是洛谷的模板题的。

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 = 200000 + 5, M = 300000 + 5;

int n, m, fa[N], sdom[N], idom[N], dfn[N], id[N], cnt, ans[N];

struct Graph {
    int fr[M << 1], to[M << 1], h[N], tot;
    void cal (int u) {
        ans[u] = 1;
        for (int i = h[u]; i; i = fr[i]) {
            cal (to[i]);
            ans[u] += ans[to[i]];
        }
    }
    inline void add (int u, int v) {
        ++tot;
        fr[tot] = h[u];
        to[tot] = v;
        h[u] = tot;
    }
    void dfs (int u) {
        dfn[u] = ++cnt;
        id[cnt] = u;
        for (int i = h[u]; i; i = fr[i]) {
            if (!dfn[to[i]]) {
                dfs (to[i]);
                fa[to[i]] = u;
            }
        }
    }
}pos, neg, tree, Ans;

struct UnionSet {
    int f[N], val[N];
    inline void init (int n = N - 5) {
        for (int i = 1; i <= n; ++i) {
            f[i] = i;
            val[i] = i;
            sdom[i] = i;
        }
    }
    inline void find (int u) {
        if (f[u] == u) {
            return ;
        }
        find (f[u]);
        int rt = f[f[u]];
        if (dfn[sdom[val[f[u]]]] < dfn[sdom[val[u]]]) {
            val[u] = val[f[u]];
        }
        f[u] = rt;
    }
}st;

inline void LT () {
    st.init(n);
    for (int i = cnt; i >= 2; --i) {
        int now = id[i];
        for (int j = neg.h[now]; j; j = neg.fr[j]) {
            int v = neg.to[j];
            st.find (v);
            if (dfn[sdom[now]] > dfn[sdom[st.val[v]]]) {
                sdom[now] = sdom[st.val[v]];
            }
        }
        tree.add(sdom[now], now);
        st.f[now] = fa[now];
        now = fa[now];
        for (int j =tree.h[now]; j; j = tree.fr[j]) {
            int v = tree.to[j];
            st.find(v);
            if (sdom[st.val[v]] == now) {
                idom[v] = now;
            }
            else {
                idom[v] = st.val[v];
            }
        }
    }
    for (int i = 1; i <= n; ++i) {
        int now = id[i];
        if (sdom[now] != idom[now]) {
            idom[now] = idom[idom[now]];
        }
    }
}

int main () {
    scanf ("%d%d", &n, &m);
    for (int i = 1; i <= m; ++i) {
        int x, y;
        scanf ("%d%d", &x, &y);
        pos.add (x, y);
        neg.add (y, x);
    }
    pos.dfs (1);
    LT ();
    for (int i = 1; i <= n; ++i) {
        if (idom[i]) {
            Ans.add(idom[i], i);
        }
    }
    Ans.cal (1);
    for (int i = 1; i <= n; ++i) {
        printf ("%d ", ans[i]);
    }
    return 0;
}

Concluion

大概就这样。

两天的时间打出了我的支配树代码,接下来想花一些时间做一些相关的题目,熟悉一下。

话说这和Conclusion有什么关系

标签:sdom,教程,val,int,支配,st,简记,dfn,now
来源: https://www.cnblogs.com/ChiTongZ/p/11178633.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有