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

    P2597 [ZJOI2012]灾难

    题目描述

    见链接


    Solution

    建立支配树即可


    Addition

    步骤:

    1. 反向建边
    2. 拓扑排序
    3. 按反拓扑序依次加入支配树节点

    加入节点时, 取其所有原图父亲的LCALCA作新树的父亲


    Attention

    两个字符1,01,0调了 6hours6-hours !!!
    要时刻注意循环边界 !!!


    Code

    #include<bits/stdc++.h>
    #define reg register
    
    const int maxn = 80000;
    
    int N, cnt, num0, Lim;
    int B[maxn], In[maxn];
    int F[maxn][18];
    int dep[maxn];
    int head[maxn];
    int size[maxn];
    
    struct Edge{ int nxt, to; } edge[maxn<<1];
    
    void Add(int from, int to){
            edge[++ num0] = (Edge){ head[from], to };
            head[from] = num0;
    }
    
    int LCA(int a, int b){
            if(dep[a] < dep[b]) std::swap(a, b);
            for(reg int i = 17; i >= 0; i --)
                    if(dep[F[a][i]] >= dep[b]) a = F[a][i];
            if(a == b) return a;
            for(reg int i = 17; i >= 0; i --)
                    if(F[a][i] != F[b][i]) a = F[a][i], b = F[b][i];
            return F[a][0];
    }
    
    void DFS(int k, int fa){
            size[k] = 1;
            for(reg int i = head[k]; i; i = edge[i].nxt){
                    if(i <= Lim) continue ;
                    int to = edge[i].to;
                    if(to == fa) continue ;
                    DFS(to, k);
                    size[k] += size[to];
            }
    }
    
    int main(){
            scanf("%d", &N);
            for(reg int i = 1; i <= N; i ++){
                    int x;
                    scanf("%d", &x);
                    while(x) Add(i, x), In[x] ++, scanf("%d", &x);
            }
            Lim = num0;
            std::queue <int> Q;
            for(reg int i = 1; i <= N; i ++) if(!In[i]) Q.push(i);
            while(!Q.empty()){
                    int ft = Q.front(); Q.pop();
                    B[++ cnt] = ft;
                    for(reg int i = head[ft]; i; i = edge[i].nxt){
                            int to = edge[i].to;
                            if(!(-- In[to])) Q.push(to); 
                    }
            }
            dep[N+1] = 1;
            for(reg int i = 0; i <= 17; i ++) F[N+1][i] = N+1;
            for(reg int i = cnt; i >= 1; i --){
                    int s = N+1, x = B[i];
                    if(head[x]){
                            s = edge[head[x]].to;
                            for(reg int j = head[x]; j; j = edge[j].nxt) 
                                    s = LCA(s, edge[j].to);
                    }
                    dep[x] = dep[s] + 1, F[x][0] = s;
                    Add(s, x);
                    for(reg int j = 1; j <= 17; j ++) F[x][j] = F[F[x][j-1]][j-1];
            }
            DFS(N+1, 0);
            for(reg int i = 1; i <= N; i ++) printf("%d
    ", size[i] - 1);
            return 0;
    }
    
    
  • 相关阅读:
    webpack入门
    Javascript隐式转换
    一个最小手势库的实现
    运用JS设置cookie、读取cookie、删除cookie
    不同浏览器下兼容文本两端对齐
    使用CSS3实现一个3D相册
    JavaScript 火的有点过头了,但又能火多久呢?
    强大的css3
    CSS3与页面布局学习总结
    红米手机真机调试问题记录
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822668.html
Copyright © 2011-2022 走看看