【BZOJ2815】【ZJOI2012】灾难 阿米巴和小强题 动态倍增LCA 灾难树

广告:

#include <stdio.h>
int main()
{
    puts("转载请注明出处[vmurder]谢谢");
    puts("网址:blog.csdn.net/vmurder/article/details/44104163");
}

题意:

原题面请见 JSShining 博客

http://www.cnblogs.com/JS-Shining/archive/2013/01/12/2857429.html

题解:

我们构建一颗灾难树,使得一个节点的任意一个祖先灭绝,则其会灭绝。
则可以按照拓扑序扫每个节点,然后加入到灾难树中时只需要把它的父亲赋成它所有食物的LCA就好了。
我们可以动态处理每个节点的倍增lca数组 fi,j 表示i的第 (1<<j) 高祖先。

代码:

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 70000
#define M 600000
#define LOGN 20
using namespace std;
struct KSD
{
    int v,next;
}e[M],E[M],Ee[M];
int head[N],cnt,HEAD[N],CNT,Head[N];
inline void add(int u,int v)
{
    e[++cnt].v=v;
    Ee[cnt].v=u;
    e[cnt].next=head[u];
    Ee[cnt].next=Head[v];
    Head[v]=head[u]=cnt;
}
inline void ADD(int u,int v)
{
    E[++CNT].v=v;
    E[CNT].next=HEAD[u];
    HEAD[u]=CNT;
}
int f[N][LOGN],dep[N];
int getlca(int a,int b)
{
    int i;
    if(dep[a]<dep[b])swap(a,b);
    for(i=LOGN-1;i>=0;i--)
        if(dep[f[a][i]]>=dep[b])a=f[a][i];
    if(a==b)return a;
    for(i=LOGN-1;i>=0;i--)
        if(f[a][i]!=f[b][i])
            a=f[a][i],b=f[b][i];
    return f[a][0];
}
int d[N],ans[N];
queue<int>q;
int dfs(int x)
{
    ans[x]=1;
    for(int i=HEAD[x];i;i=E[i].next)
        ans[x]+=dfs(E[i].v);
    return ans[x];
}
int n;
int main()
{
    int i,j,k;
    int a,b,c;
    int u,v,lca;

    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        while(scanf("%d",&a),a)
        {
            add(a,i);
            d[i]++;
        }
    }
    for(i=1;i<=n;i++)if(!d[i])add(n+1,i),d[i]=1;
    q.push(n+1);
    while(!q.empty())
    {
        u=q.front(),q.pop();
        lca=0;
        for(i=Head[u];i;i=Ee[i].next)
        {
            v=Ee[i].v;
            if(i==Head[u])lca=v;
            else lca=getlca(lca,v);
        }
        for(i=head[u];i;i=e[i].next)
        {
            d[v=e[i].v]--;
            if(!d[v])q.push(v);
        }
        if(lca)
        {
            ADD(lca,u),f[u][0]=lca;
            for(j=1;j<LOGN;j++)
                f[u][j]=f[f[u][j-1]][j-1];
        }
        dep[u]=dep[lca]+1;
    }
    dfs(n+1);
    for(i=1;i<=n;i++)printf("%d\n",ans[i]-1);
    return 0;
}

你可能感兴趣的:(LCA,灾难,Zjoi2012,BZOJ2815,阿米巴和小强)