• hdu 4695 Important Sisters


    支配树模版题~

    这东西似乎非常好写……

    但是证明好长好长啊~

    $$sdom(u) = min{{v|(v, u) in E, dfn(v) < dfn(u)}cup{sdom(q)|dfn(q)>dfn(u), exists  (p, x) in E, q in path(S, p)}}$$

    前一半是走前向边或者树边,后一半是走横叉边或者返祖边

    $$idom(u) = egin{cases}sdom(u)& ext{ if } sdom(v)= sdom(u)\ idom(v) & ext{ if } sdom(v)<sdom(u) end{cases}$$

    其中(v)代表((sdom(u), u])之中(sdom)最小的那一个点。

    #include <bits/stdc++.h>
    using namespace std;
    #define LL long long
    const int N = 200000;
    int n, m;
    int dfn[N], lst[N], id[N], sd[N], paid[N], mns[N];
    int anc[N], par[N], tot;
    vector <int> bi[N], bp[N], bb[N];
    LL sum[N];
    void dfs(int t)
    {
        dfn[t] = ++ tot; lst[tot] = t;
        for (int i = 0; i < bi[t].size(); ++ i)
            if (!dfn[bi[t][i]])
                dfs(bi[t][i]), par[bi[t][i]] = t;
    }
    int check_min(int a, int b)
    {
        if (dfn[a] < dfn[b]) return a; else return b;
    }
    int find_anc(int t)
    {
        if (anc[t] == t) return t;
        else
        {
            int a = find_anc(anc[t]);
            if (a != anc[t] && dfn[sd[mns[anc[t]]]] < dfn[sd[mns[t]]])
                mns[t] = mns[anc[t]];
            return anc[t] = a;
        }
    }
    int main()
    {
        while (scanf("%d%d", &n, &m) == 2)
        {
            for (int i = 0; i <= n; ++ i)
                bi[i].clear(), bp[i].clear(), bb[i].clear();
            for (int i = 0; i <= n; ++ i)
                dfn[i] = lst[i] = par[i] = id[i] = sd[i] = paid[i] = sum[i] = 0;
            for (int i = 1; i <= n; ++ i) anc[i] = mns[i] = i;
            tot = 0;
            for (int i = 1; i <= m; ++ i)
            {
                int a, b;
                scanf("%d%d", &a, &b);
                bi[a].push_back(b);
                bp[b].push_back(a);
            }
            dfs(n);
            for (int i = n; ; -- i)
            {
                for (int j = 0; j < bb[lst[i]].size(); ++ j)
                {
                    find_anc(bb[lst[i]][j]);
                    if (sd[mns[bb[lst[i]][j]]] == sd[bb[lst[i]][j]])
                        id[bb[lst[i]][j]] = sd[bb[lst[i]][j]];
                    else
                        paid[bb[lst[i]][j]] = mns[bb[lst[i]][j]];
                }
                if (i == 1) break;
                sd[lst[i]] = par[lst[i]];
                for (int j = 0; j < bp[lst[i]].size(); ++ j) if (dfn[bp[lst[i]][j]])
                {
                    if (dfn[bp[lst[i]][j]] < i)
                        sd[lst[i]] = check_min(sd[lst[i]], bp[lst[i]][j]);
                    else
                    {
                        find_anc(bp[lst[i]][j]);
                        sd[lst[i]] = check_min(sd[lst[i]], sd[mns[bp[lst[i]][j]]]);
                    }
                }
                mns[lst[i]] = lst[i];
                anc[lst[i]] = par[lst[i]];
                bb[sd[lst[i]]].push_back(lst[i]);
            }
            for (int i = 1; i <= n; ++ i) if (paid[lst[i]])
                id[lst[i]] = id[paid[lst[i]]];
            // for (int i = 1; i <= n; ++ i)
                // printf("%d
    ", id[i]);
            for (int i = 1; i <= n; ++ i)
                sum[lst[i]] = sum[id[lst[i]]] + lst[i];
            for (int i = 1; i <= n; ++ i)
                printf("%lld%c", sum[i], (i == n? '
    ': ' '));
        }
    }
  • 相关阅读:
    老友记实战,17上
    老友记实战,9下
    老友记实战,5下
    公共样式base.css
    单选框radio总结(获取值、设置默认选中值、样式)
    js tab切换
    HTTP状态码100、200、300、400、500、600的含义
    微信小程序事件绑定
    微信小程序获取手机验证码
    js滚动到指定位置导航栏固定顶部
  • 原文地址:https://www.cnblogs.com/AwD-/p/8099300.html
Copyright © 2020-2023  润新知