Luogu P2597 [ZJOI2012]灾难

一道非常综合的好题然后就莫名其妙地知道了动态LCA的求法

果然是ZJOI的题目,只能说这思路服了

首先我们发现每次操作只会灭绝一种动物,然后我们想一下就知道如果有\(n(n>=2)\)个食物的动物就不会灭绝。

然后我们YY一个叫灭绝树的东西,在这个树上的点都满足一个性质:当一个节点被割去时,以它为根的整棵子树对应的动物都会灭亡。

然后我们只需要考虑如何搞出这个树了。

然后我们再YY一个虚拟节点0,让它向所有生产者连边,我们可以形象得理解成太阳

然后我们将题目中的树反向建边,然后就变成了这样:

然后我们发现5号点很难受,因为有两个点连向它。那么如果只割一个点怎么让5号点灭绝。

答案很简单:只需要让它的两个父节点都灭绝即可

然后我们看要让2,3号点都灭绝,那么:

只需要让1灭绝即可。那么1与2,3的关系就很简单了:1是2,3的LCA

那么就很好办了,我们只需要按顺序找出每一个点的所有父节点的LCA,然后在灭绝树上把这个点挂在它的LCA下面即可。

但是这个顺序怎么办,我们注意到题目中提到了:

这个图没有环。

然后就我们从0开始拓扑排序即可确定这个顺序,然后就只求LCA了

这里注意因为我们没有刚开始就把图建出来,所以DFS序+RMQ和Tarjan的方法就不能用了。

所以我们用倍增,每次将一个点挂上树时然后单独更新它的LCA信息

然后就可以解决了,不得不吐槽一下这道题开了三个邻接表,还是很狗的,因为这个调了很久

CODE

#include<cstdio>
#include<cstring>
using namespace std;
const int N=70000,P=20;
struct edge
{
    int to,next;
}e[N<<2],re[N<<2],new_e[N<<1];
int head[N],rhead[N],new_head[N],dep[N],ru[N],q[N],father[N][P],size[N],tot,sum,cnt,rcnt,new_cnt,n,x,rt;
inline char tc(void)
{
    static char fl[100000],*A=fl,*B=fl;
    return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
    x=0; char ch=tc();
    while (ch<‘0‘||ch>‘9‘) ch=tc();
    while (ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=tc();
}
inline void write(int x)
{
    if (x/10) write(x/10);
    putchar(x%10+‘0‘);
}
inline void add(int x,int y)
{
    e[++cnt].to=y; e[cnt].next=head[x]; head[x]=cnt;
}
inline void radd(int x,int y)
{
    re[++rcnt].to=y; re[rcnt].next=rhead[x]; rhead[x]=rcnt;
}
inline void new_add(int x,int y)
{
    new_e[++new_cnt].to=y; new_e[new_cnt].next=new_head[x]; new_head[x]=new_cnt;
}
inline void swap(int &a,int &b)
{
    int t=a; a=b; b=t;
}
inline void top_sort(void)
{
    register int i; int H=0,T=0;
    for (i=1;i<=n;++i)
    if (!ru[i]) q[++T]=i,father[i][0]=rt,dep[i]=1,new_add(rt,i),new_add(i,rt);
    while (H<T)
    {
        int now=q[++H];
        for (i=head[now];i!=-1;i=e[i].next)
        if (!(--ru[e[i].to])) q[++T]=e[i].to;
    }
}
inline void rebuild(int now)
{
    for (register int i=0;i<P-1;++i)
    if (father[now][i]^-1) father[now][i+1]=father[father[now][i]][i];
}
inline int LCA(int x,int y)
{
    register int i;
    if (dep[x]<dep[y]) swap(x,y);
    for (i=P-1;i>=0;--i)
    if (father[x][i]^-1&&dep[father[x][i]]>=dep[y]) x=father[x][i];
    if (!(x^y)) return x;
    for (i=P-1;i>=0;--i)
    if (father[x][i]^-1&&father[y][i]^-1&&father[x][i]^father[y][i]) x=father[x][i],y=father[y][i];
    return father[x][0];
}
inline void get_tree(void)
{
    register int i,j;
    for (i=1;i<=n;++i)
    {
        int now=q[i];
        if (!(father[now][0]^-1))
        {
            int fa=-1;
            for (j=rhead[now];j!=-1;j=re[j].next)
            if (fa^-1) fa=LCA(fa,re[j].to); else fa=re[j].to;
            if (!(fa^-1)) fa=0;
            father[now][0]=fa; new_add(fa,now); new_add(now,fa); dep[now]=dep[fa]+1; rebuild(now);
        }
    }
}
inline void DFS(int now,int fa)
{
    size[now]=1;
    for (register int i=new_head[now];i!=-1;i=new_e[i].next)
    if (new_e[i].to^fa) DFS(new_e[i].to,now),size[now]+=size[new_e[i].to];
}
int main()
{
    //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
    register int i; read(n); memset(father,-1,sizeof(father));
    memset(e,-1,sizeof(e)); memset(head,-1,sizeof(head));
    memset(re,-1,sizeof(re)); memset(rhead,-1,sizeof(rhead));
    memset(new_e,-1,sizeof(new_e)); memset(new_head,-1,sizeof(new_head));
    for (i=1;i<=n;++i)
    for (read(x);x;read(x))
    add(x,i),radd(i,x),++ru[i];
    top_sort(); get_tree(); DFS(rt,-1);
    for (i=1;i<=n;++i)
    write(size[i]-1),putchar(‘\n‘);
    return 0;
}

原文地址:https://www.cnblogs.com/cjjsb/p/9146700.html

时间: 2024-11-02 23:21:47

Luogu P2597 [ZJOI2012]灾难的相关文章

P2597 [ZJOI2012]灾难——拓扑,倍增,LCA

最近想学支配树,但是基础还是要打好了的: P2597 [ZJOI2012]灾难 这道题是根据食物链链接出一个有向图的关系,求一个物种的灭绝会连带几种物种的灭绝: 求得就是一个点能支配几个点: 如果一个点没有食物了就会灭绝,那他的支配点就是他所有食物的LCA: LCA死了,食物都死了,他也就死了: 我们先根据吃和被吃建图,连一条他和食物的有向边: 我们处理出拓扑序,入度为零的点就是终极捕食者: 重新建一个树,每个点支配的数量就是他为根的子树大小-1: 我们只需要将他和食物的LCA连边即可:这个时候

[bzoj2815] [洛谷P2597] [ZJOI2012] 灾难

Description 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,如果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引发一系列的生态灾难. 学过生物的阿米巴告诉小强,草原是一个极其稳定的生态系统.如果蚂蚱灭绝了,小鸟照样可以吃别的虫子,所以一个物种的灭绝并不一定会引发重大的灾难. 我们现在从专业一点的角度来看这个问题.我们用一种叫做食物网的有向图来描述生物之间的关系: 一个食物网有N个点,代表N种生物,如果生物x可以吃生物y,那么从y向x连

P2597 [ZJOI2012]灾难 拓扑排序

这个题有点意思,正常写法肯定会T,然后需要优化.先用拓扑排序重构一遍树,然后进行一个非常神奇的操作:把每个点放在他的食物的lca上,然后计算的时候直接dfs全加上就行了.为什么呢,因为假如你的食物的lca死了,你就很自然的死了.这个题还要加一个超级源点,一开始我没加只拿了20分.但是不知道为什么,后来想到有可能一个兄弟能吃两个生产者,在查询lca的时候会跪...剩下就没啥了,顺便练一下倍增求lca. 题干: 题目描述 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,如果蚂蚱被他们

P2597 [ZJOI2012]灾难(lca)

题目描述 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,如果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引发一系列的生态灾难. 学过生物的阿米巴告诉小强,草原是一个极其稳定的生态系统.如果蚂蚱灭绝了,小鸟照样可以吃别的虫子,所以一个物种的灭绝并不一定会引发重大的灾难. 我们现在从专业一点的角度来看这个问题.我们用一种叫做食物网的有向图来描述生物之间的关系: 一个食物网有N个点,代表N种生物,如果生物x可以吃生物y,那么从y向x连一个有向边.

【BZOJ2815】[ZJOI2012]灾难 拓补排序+LCA

[BZOJ2815][ZJOI2012]灾难 题目描述 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引发一系列的生态灾难. 学过生物的阿米巴告诉小强,草原是一个极其稳定的生态系统.如果蚂蚱灭绝了,小鸟照样可以吃别的虫子,所以一个物种的灭绝并不一定会引发重大的灾难. 我们现在从专业一点的角度来看这个问题.我们用一种叫做食物网的有向图来描述生物之间的关系: 一个食物网有N个点,代表N种生物,如果生物

bzoj 2815: [ZJOI2012]灾难

Description 阿米巴是小强的好朋友.阿米巴和小强在草原上捉蚂蚱.小强突然想,如果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引发一系列的生态灾难. 学过生物的阿米巴告诉小强,草原是一个极其稳定的生态系统.如果蚂蚱灭绝了,小鸟照样可以吃别的虫子,所以一个物种的灭绝并不一定会引发重大的灾难.我们现在从专业一点的角度来看这个问题.我们用一种叫做食物网的有向图来描述生物之间的关系: 一个食物网有 N个点,代表 N 种生物,如果生物 x 可以吃生物 y,那么从

【bzoj2815】[ZJOI2012]灾难 拓扑排序+构造+倍增LCA

题目描述(转自洛谷) 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引发一系列的生态灾难. 学过生物的阿米巴告诉小强,草原是一个极其稳定的生态系统.如果蚂蚱灭绝了,小鸟照样可以吃别的虫子,所以一个物种的灭绝并不一定会引发重大的灾难. 我们现在从专业一点的角度来看这个问题.我们用一种叫做食物网的有向图来描述生物之间的关系: 一个食物网有N个点,代表N种生物,如果生物x可以吃生物y,那么从y向x连一个

[ZJOI2012]灾难

题目:洛谷P2597.BZOJ2815(然而此处并没有题面).codevs1210 题目大意:给你一个食物网,要你求每个生物的“毁灭值”(毁灭值为该生物灭绝后,其他跟着它灭绝的生物的总数). 解题思路:拓扑排序+LCA. 先假设所有生产者都吃“太阳”,然后对它们进行拓扑排序.以拓扑序依次加点,每次将要加的点与所有父亲求LCA,此时LCA或LCA的任一父亲节点死亡,则该点灭绝.所以直接把该点变为LCA的子节点即可.此时每个节点的毁灭值为以它为根的子树的节点的个数. 不过我的代码在codevs上莫名

2815: [ZJOI2012]灾难 - BZOJ

题目描述 Description    阿米巴是小强的好朋友.    阿米巴和小强在草原上捉蚂蚱.小强突然想,如果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引发一系列的生态灾难.    学过生物的阿米巴告诉小强,草原是一个极其稳定的生态系统.如果蚂蚱灭绝了,小鸟照样可以吃别的虫子,所以一个物种的灭绝并不一定会引发重大的灾难.    我们现在从专业一点的角度来看这个问题.我们用一种叫做食物网的有向图来描述生物之间的关系:    一个食物网有N个点,代表N种生物