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

    这道题好仙啊,不过暴力都能拿70pts。

    考虑每个点的贡献,会发现,它只对它所有食物的LCA及LCA到根的路径上的节点有灾难值为一的贡献。

    然后就是建树啦,我们必须保证当前节点的所有食物都已建好树,所以top_sort,在更新入度到为零时,就求出它所有食物的LCA,

    然后将LCA做为此节点的父节点,并令sum(lca)++,更新ST表。。。

    最后还要统计节点对LCA到根的节点的贡献,做一次树上前缀和即可。这个玩意什么时候叫做树上前缀和了QAQ。。其实特别low。

    代码较丑,搞了三个链式前向星,最后还因为超级源点的深度和生产者的深度都赋成了1卡了半天。。。。

    Code:

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #define N 100000
    using namespace std;
    queue<int> q;
    int n,Head[N],ver[N],nex[N],du[N],f[N][21],d[N],tot,sum[N];
    int Head2[N],ver2[N],nex2[N],tot2;
    int Head3[N],ver3[N],nex3[N],tot3;
    inline int read(){
        char c=getchar();int x=0,flag=1;
        while(c<'0' || c>'9'){if(c=='-') flag=-1;c=getchar();}
        while(c>='0' && c<='9') x=(x<<1)+(x<<3)+c-'0',c=getchar();
        return x*flag;
    }
    void add(int x,int y){ver[++tot]=y;nex[tot]=Head[x];Head[x]=tot;}
    void add2(int x,int y){ver2[++tot2]=y;nex2[tot2]=Head2[x];Head2[x]=tot2;}
    void add3(int x,int y){ver3[++tot3]=y;nex3[tot3]=Head3[x];Head3[x]=tot3;}
    int LCA(int x,int y){
        if(d[x]<d[y]) swap(x,y);
        for(int i=20;i>=0;i--) if(d[f[x][i]]>=d[y]) x=f[x][i];
        if(x==y) return x;
        for(int i=20;i>=0;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
        return f[x][0];
    }
    void dfs(int x){
        sum[x]=1;
        for(int i=Head3[x];i;i=nex3[i]){
            int y=ver3[i];dfs(y);
            sum[x]+=sum[y];
        }
    }
    void top_sort(){
        for(int i=1;i<=n;i++) if(!du[i]) add(0,i),add2(i,0);
        q.push(0);
        while(q.size()){
            int x=q.front();q.pop();
            for(int i=Head[x];i;i=nex[i]){
                int y=ver[i];du[y]--;
                if(du[y]<=0){
                    int lca=x;
                    for(int j=Head2[y];j;j=nex2[j]){
                        int k=ver2[j];if(k==x) continue;
                        lca=LCA(lca,k);
                    }
                    f[y][0]=lca;d[y]=d[lca]+1;add3(lca,y);
                    for(int k=1;k<=20;k++) f[y][k]=f[f[y][k-1]][k-1];
                    q.push(y);
                }
            }
        }
    }
    int main(){
        n=read();d[0]=1;
        for(int i=1;i<=n;i++){
            int x;
            while(scanf("%d",&x) && x){add(x,i);add2(i,x);du[i]++;}
        }
        top_sort();dfs(0);
        for(int i=1;i<=n;i++) printf("%d
    ",sum[i]-1);
    }
  • 相关阅读:
    防止域名恶意指向的解决办法
    Spring @Configuration @Import
    CAS 集成认证
    远程桌面登录蓝色屏幕、不显示桌面怎么解决?
    终端服务器超出了最大允许连接数
    Fiddler 常见几种解决捕获不到请求的方法
    android TimerTask 的简单应用
    Android 数字签名学习笔记
    Android 遍历卡数据并按图片,音乐等分类保存
    Android 最简单的SD卡文件遍历程序
  • 原文地址:https://www.cnblogs.com/SyhAKIOI/p/11680336.html
Copyright © 2011-2022 走看看