• Important Sisters【HDU-4694】【Dominator Tree】


    题目链接

      有N个妹妹,然后从N号妹妹开始发消息,现在每个妹妹都想知道消息是什么,但是消息只有M条有向路径来传播,然后现在询问每个点u,从N号妹妹到她的路径上有哪些必经点,将这些必经点的点序号求和后输出。

      所以,这就是一个一般图上的Dominator Tree问题,一般图的支配树问题,直接建支配树,然后求一个“深度”即可。然后因为是多组输入,记得初始化。

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <string>
    #include <cstring>
    #include <algorithm>
    #include <limits>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <set>
    #include <map>
    #include <bitset>
    #include <unordered_map>
    #include <unordered_set>
    #define lowbit(x) ( x&(-x) )
    #define pi 3.141592653589793
    #define e 2.718281828459045
    #define INF 0x3f3f3f3f
    #define HalF (l + r)>>1
    #define lsn rt<<1
    #define rsn rt<<1|1
    #define Lson lsn, l, mid
    #define Rson rsn, mid+1, r
    #define QL Lson, ql, qr
    #define QR Rson, ql, qr
    #define myself rt, l, r
    #define pii pair<int, int>
    #define MP(a, b) make_pair(a, b)
    using namespace std;
    typedef unsigned long long ull;
    typedef unsigned int uit;
    typedef long long ll;
    const int maxN = 5e4 + 7, maxM = 2e5 + 7;
    int N, M;
    namespace Graph
    {
        int head[maxN], cnt;
        struct Eddge
        {
            int nex, to;
            Eddge(int a=-1, int b=0):nex(a), to(b) {}
        } edge[maxM];
        inline void addEddge(int u, int v)
        {
            edge[cnt] = Eddge(head[u], v);
            head[u] = cnt++;
        }
        inline void init()
        {
            cnt = 0;
            for(int i=1; i<=N; i++) head[i] = -1;
        }
    };
    using namespace Graph;
    namespace Dominator
    {
        int tim;
        int dfn[maxN], rid[maxN], fa[maxN], sdom[maxN], idom[maxN];
        int fo[maxN], vo[maxN];
        vector<int> pre[maxN], bkt[maxN];
        int findf(int p)
        {
            if(fo[p]==p) return p;
            int r = findf(fo[p]);
            if(sdom[vo[fo[p]]]<sdom[vo[p]]) vo[p] = vo[fo[p]];
            return fo[p] = r;
        }
        inline int eval(int p)
        {
            findf(p);
            return vo[p];
        }
        void dfs(int p)
        {
            rid[dfn[p]=++tim] = p; sdom[p] = dfn[p];
            for(int i=head[p]; ~i; i=edge[i].nex) if(!dfn[edge[i].to])
            {
                dfs(edge[i].to);
                fa[edge[i].to] = p;
            }
        }
        void work()
        {
            int p;
            dfs(N);
            for(int i=tim; i>=2; i--)
            {
                p = rid[i];
                for(int k : pre[p]) if(dfn[k]) sdom[p] = min(sdom[p], sdom[eval(k)]);
                bkt[rid[sdom[p]]].push_back(p);
                int fp = fa[p];
                fo[p] = fa[p];
                for(int v : bkt[fp])
                {
                    int u = eval(v);
                    idom[v] = sdom[u] == sdom[v] ? fp : u;
                }
                bkt[fp].clear();
            }
            for(int i=2; i<=tim; i++) { p = rid[i]; idom[p] = idom[p] == rid[sdom[p]] ? idom[p] : idom[idom[p]]; }
            for(int i=2; i<=tim; i++) { p = rid[i]; sdom[p] = rid[sdom[p]]; }
        }
        inline void link(int a, int b)
        {
            addEddge(a, b);
            pre[b].push_back(a);
        }
        void init()
        {
            tim = 0;
            for(int i=1; i<=N; i++)
            {
                dfn[i] = idom[i] = 0;
                fo[i] = vo[i] = i;
                pre[i].clear();
                bkt[i].clear();
            }
        }
    };
    using namespace Dominator;
    vector<int> E[maxN];
    ll siz[maxN];
    void last_dfs(int u)
    {
        siz[u] += u;
        for(int v : E[u])
        {
            siz[v] = siz[u];
            last_dfs(v);
        }
    }
    int main()
    {
        while(scanf("%d%d", &N, &M) != EOF)
        {
            Graph::init();
            Dominator::init();
            for(int i=1, u, v; i<=M; i++)
            {
                scanf("%d%d", &u, &v);
                link(u, v);
            }
            work();
            for(int i=1; i<=N; i++) { E[i].clear(); siz[i] = 0; }
            for(int i=1; i<N; i++) E[idom[i]].push_back(i);
            siz[N] = 0;
            last_dfs(N);
            for(int i=1; i<=N; i++) printf("%lld%c", siz[i], i == N ? '
    ' : ' ');
        }
        return 0;
    }
  • 相关阅读:
    HTTP协议
    DNS解析原理
    数据库 怎么配置多实例
    mysql回表
    Oracle进程说明
    Oracle动态和静态参数文件和控制文件
    Oracle数据库的启动和关闭过程
    Mysql索引
    sqlserver备份还原
    oracle undo表空间异常激增排查
  • 原文地址:https://www.cnblogs.com/WuliWuliiii/p/13693093.html
Copyright © 2020-2023  润新知