zoukankan      html  css  js  c++  java
  • hdu 4694 Important Sisters 支配树

    题目大意

    给定一个n个点m条边的有向图,以n为源点.对于一个点u,求在所有n->u的路径上都出现的点的编号之和.
    n <= 50000,m <= 1000000

    题解

    终于有时间来学支配树了。
    支配树裸题,直接用支配树模板去搞就好了。
    关于支配树,我正在写这个ppt
    写好了我把链接发到这个博客上有想看的可以看
    (不知不觉,一个大坑)
    UPD : 课件写好了,想要看的可以私信~~

    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    inline void read(int &x){
        x=0;static char ch;static bool flag;flag = false;
        while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
        while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
    }
    #define rg register int
    #define rep(i,a,b) for(rg i=(a);i<=(b);++i)
    #define per(i,a,b) for(rg i=(a);i>=(b);--i)
    const int maxn = 50010;
    const int maxm = 100010;
    struct Graph{
        struct Edge{
            int to,next;
        }G[maxm];
        int head[maxn],cnt;
        void clear(){
            memset(head,0,sizeof head);
            cnt = 0;
        }
        void add(int u,int v){
            G[++cnt].to = v;
            G[cnt].next = head[u];
            head[u] = cnt;
        }
    }ori,inv,nwg;
    int ufa[maxn],pos[maxn],ido[maxn],sdo[maxn];
    int find(int x){
        if(x == ufa[x]) return ufa[x];
        int r = find(ufa[x]);
        if(sdo[pos[ufa[x]]] < sdo[pos[x]]) pos[x] = pos[ufa[x]];
        return (ufa[x] = r);
    }
    inline int eval(int x){
        find(x);return pos[x];
    }
    int n,m,dfn[maxn],seq[maxn],dfs_clock;
    int fa[maxn];
    void dfs(int u){
        dfn[u] = ++ dfs_clock;
        seq[dfs_clock] = u;
        sdo[u] = dfs_clock;
        for(int i = ori.head[u],v;i;i = ori.G[i].next){
            v = ori.G[i].to;
            if(dfn[v]) continue;
            fa[v] = u;
            dfs(v);
        }
    }
    int sum[maxn];
    void dfs(int u,int f){
        for(rg i = nwg.head[u],v;i;i=nwg.G[i].next){
            v = nwg.G[i].to;
            if(v == f) continue;
            sum[v] = sum[u] + v;
            dfs(v,u);
        }
    }
    vector<int>ve[maxn];
    int main(){
        while(scanf("%d%d",&n,&m) != EOF){
            rep(i,1,n) ufa[i] = i,pos[i] = i;
            ori.clear();inv.clear();nwg.clear();
            rep(i,1,n) ve[i].clear(),dfn[i] = seq[i] = ido[i] = sdo[i] = sum[i] = fa[i] = 0;
            dfs_clock = 0;
            int u,v;
            rep(i,1,m){
                read(u);read(v);
                ori.add(u,v);
                inv.add(v,u);
            }
            dfs(n);
            per(id,dfs_clock,2){
                u = seq[id];
                for(int i = inv.head[u];i;i=inv.G[i].next) 
                    if(dfn[inv.G[i].to]) sdo[u] = min(sdo[u],sdo[eval(inv.G[i].to)]);
                ve[seq[sdo[u]]].push_back(u);
                int f = fa[u];ufa[u] = fa[u];
                for(vector<int>::iterator it = ve[f].begin();it != ve[f].end();++it){
                    int x = eval(*it);
                    ido[*it] = sdo[*it] == sdo[x] ? f : x;
                }ve[f].clear();
            }
            rep(i,2,dfs_clock) u = seq[i],ido[u] = ido[u] == seq[sdo[u]] ? ido[u] : ido[ido[u]];
            rep(i,1,n-1) nwg.add(ido[i],i);sum[n] = n;
            dfs(n,n);
            rep(i,1,n){
                printf("%d",sum[i]);
                if(i != n) putchar(' ');
                else putchar('
    ');
            }
        }
        return 0;
    }
    
    
  • 相关阅读:
    HDU 5213 分块 容斥
    HDU 2298 三分
    HDU 5144 三分
    HDU 5145 分块 莫队
    HDU 3938 并查集
    HDU 3926 并查集 图同构简单判断 STL
    POJ 2431 优先队列
    HDU 1811 拓扑排序 并查集
    HDU 2685 GCD推导
    HDU 4496 并查集 逆向思维
  • 原文地址:https://www.cnblogs.com/Skyminer/p/6800007.html
Copyright © 2011-2022 走看看