洛谷题目链接:[ZJOI2012]灾难

题目描述

阿米巴是小强的好朋友。

阿米巴和小强在草原上捉蚂蚱。小强突然想,如果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引发一系列的生态灾难。

学过生物的阿米巴告诉小强,草原是一个极其稳定的生态系统。如果蚂蚱灭绝了,小鸟照样可以吃别的虫子,所以一个物种的灭绝并不一定会引发重大的灾难。

我们现在从专业一点的角度来看这个问题。我们用一种叫做食物网的有向图来描述生物之间的关系:

一个食物网有N个点,代表N种生物,如果生物x可以吃生物y,那么从y向x连一个有向边。

这个图没有环。

图中有一些点没有连出边,这些点代表的生物都是生产者,可以通过光合作用来生存; 而有连出边的点代表的都是消费者,它们必须通过吃其他生物来生存。

如果某个消费者的所有食物都灭绝了,它会跟着灭绝。

我们定义一个生物在食物网中的“灾难值”为,如果它突然灭绝,那么会跟着一起灭绝的生物的种数。

举个例子:在一个草场上,生物之间的关系是:

如果小强和阿米巴把草原上所有的羊都给吓死了,那么狼会因为没有食物而灭绝,而小强和阿米巴可以通过吃牛、牛可以通过吃草来生存下去。所以,羊的灾难值是1。但是,如果草突然灭绝,那么整个草原上的5种生物都无法幸免,所以,草的灾难值是4。

给定一个食物网,你要求出每个生物的灾难值。

输入输出格式

输入格式:

输入文件 catas.in 的第一行是一个正整数 N,表示生物的种数。生物从 1 标

号到 N。

接下来 N 行,每行描述了一个生物可以吃的其他生物的列表,格式为用空

格隔开的若干个数字,每个数字表示一种生物的标号,最后一个数字是 0 表示列

表的结束。

输出格式:

输出文件catas.out包含N行,每行一个整数,表示每个生物的灾难值。

输入输出样例

输入样例#1:

5

0

1 0

1 0

2 3 0

2 0

输出样例#1:

4

1

0

0

0

说明

【样例说明】

样例输入描述了题目描述中举的例子。

【数据规模】

对50%的数据,N ≤ 10000。

对100%的数据,1 ≤ N ≤ 65534。

输入文件的大小不超过1M。保证输入的食物网没有环。


一句话题意: 给出一个食物链网络,当一个物种的所有食物都灭绝了这个物种才会灭绝,问一个物种灭绝后会使多少个物种灭绝.


题解: 首先可以确定处理顺序:一定要按照食物链的拓扑序来处理(从被吃的物种到吃它的物种),这样才能保证某一个物种灭绝后不会对它吃的物种造成影响.

那么在处理某个物种灭绝后造成的影响该怎么算呢?

不难想到暴力模拟,从每个点出发,直接拓扑序累加答案,这样的做法是\(O(n^2)\)的.可能有人会想到直接做一遍拓扑排序统计答案,但是这样的话就无法保证统计答案的时候某个物种的每一个食物都已经灭绝了,从而导致答案错误.

那么显然我们枚举每个点算答案的过程是不能省略的.那么该怎么样优化复杂度呢?

这里我们可以将已经算完答案的物种加入一颗树中,如果一个\(A\)灭绝后\(B\)也会灭绝,就将\(B\)连向\(A\)的儿子.这样建树的话统计答案就非常方便了,一个物种灭绝的答案就是它的子树大小.

但是这样还是有问题:一个物种可能要有多个物种灭绝才会灭绝.这时我们就可以求出这个物种所有的食物的\(LCA\),也就是说只有这个\(LCA\)灭绝了,这个物种才会灭绝.比如说这张图(引用自\(Lance1ot\)的贴图):

只有1灭绝了4才会灭绝,这样的话就将4接到1下面就可以了.

所以我们可以每次以拓扑序顺序向树中加点,并每次更新\(LCA\)的倍增数组(这里选用倍增求解\(LCA\)是因为倍增比较好在线统计,而树剖在建树的过程是离线的,也就是我们在处理之前并不知道树的形态).最后建好树后直接一遍\(dfs\)遍历整颗树.

#include<bits/stdc++.h>
using namespace std;
const int N = 300000+5; int n, val[N], gup[N][25], dep[N], in[N]; vector <int> food[N], top[N], ch[N]; int gi(){
int ans = 0, f = 1; char i = getchar();
while(i<'0' || i>'9'){ if(i == '-') f = -1; i = getchar(); }
while(i>='0' && i<='9') ans = ans*10+i-'0', i = getchar();
return ans * f;
} int lca(int x, int y){
if(dep[x] < dep[y]) swap(x, y);
for(int i=20;i>=0;i--)
if(dep[gup[x][i]] >= dep[y]) x = gup[x][i];
if(x == y) return x;
for(int i=20;i>=0;i--)
if(gup[x][i] != gup[y][i]) x = gup[x][i], y = gup[y][i];
return gup[x][0];
} void solve(int x){
int LCA = food[x][0];
for(int i=1;i<food[x].size();i++) LCA = lca(LCA, food[x][i]);
ch[LCA].push_back(x), dep[x] = dep[LCA]+1, gup[x][0] = LCA;
for(int i=1;i<=20;i++) gup[x][i] = gup[gup[x][i-1]][i-1];
} void topsort(){
queue <int> q;
for(int i=1;i<=n;i++)
if(in[i] == 0) in[i]++, top[0].push_back(i), food[i].push_back(0);
q.push(0);
while(!q.empty()){
int x = q.front(); q.pop();
for(int i=0;i<top[x].size();i++)
if(--in[top[x][i]] == 0) solve(top[x][i]), q.push(top[x][i]);
}
} void dfs(int x, int f){
for(int i=0;i<ch[x].size();i++)
dfs(ch[x][i], x), val[x] += val[ch[x][i]];
} int main(){
// freopen("data.in", "r", stdin);
ios::sync_with_stdio(false);
int x; n = gi();
for(int i=1;i<=n;i++){
x = gi();
while(x) in[i]++, top[x].push_back(i), food[i].push_back(x), x = gi();
}
for(int i=1;i<=n;i++) val[i] = 1;
topsort(), dfs(0, -1);
for(int i=1;i<=n;i++) cout << val[i]-1 << endl;
return 0;
}

[洛谷P2597] [ZJOI2012]灾难的更多相关文章

  1. 洛谷 P2597 [ZJOI2012]灾难 解题报告

    P2597 [ZJOI2012]灾难 题目描述 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,如果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引发 ...

  2. 洛谷P2597 [ZJOI2012] 灾难 [拓扑排序,LCA]

    题目传送门 灾难 题目描述 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,如果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引发一系列的生态灾难. ...

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

    Description 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,如果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引发一系列的生态灾难. 学过 ...

  4. Solution -「ZJOI2012」「洛谷 P2597」灾难

    \(\mathcal{Description}\)   link.   给定一个捕食网络,对于每个物种,求其灭绝后有多少消费者失去所有食物来源.(一些名词与生物学的定义相同 w.)   原图结点数 \ ...

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

    最近想学支配树,但是基础还是要打好了的: P2597 [ZJOI2012]灾难 这道题是根据食物链链接出一个有向图的关系,求一个物种的灭绝会连带几种物种的灭绝: 求得就是一个点能支配几个点: 如果一个 ...

  6. [洛谷P2610] [ZJOI2012]旅游

    洛谷题目链接:[ZJOI2012]旅游 题目描述 到了难得的暑假,为了庆祝小白在数学考试中取得的优异成绩,小蓝决定带小白出去旅游~~ 经过一番抉择,两人决定将T国作为他们的目的地.T国的国土可以用一个 ...

  7. 【洛谷 P2597】 [ZJOI2012]灾难(LCA)

    题目链接 考虑建一棵树,使一个生物灭绝时他的子树都会灭绝,显然这样答案就是以每个点为根的子树大小-1. 为什么原图不是一棵树,因为一个生物可能会以多个生物为食,所以按拓扑序来建树,把每个遍历到的点的父 ...

  8. 洛谷 P2611 [ZJOI2012]小蓝的好友 解题报告

    P2611 [ZJOI2012]小蓝的好友 题目描述 终于到达了这次选拔赛的最后一题,想必你已经厌倦了小蓝和小白的故事,为了回馈各位比赛选手,此题的主角是贯穿这次比赛的关键人物--小蓝的好友. 在帮小 ...

  9. P2597 [ZJOI2012]灾难

    \(\color{#0066ff}{ 题目描述 }\) 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,如果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝, ...

随机推荐

  1. mysql mariadb 密码设置

    原文:https://my.oschina.net/uyunsky/blog/109532 一.初始安装 Method 1:在/usr/local/mysql/bin/下:./mysqladmin - ...

  2. Cow Contest(最短路floyed传递闭包)

    Description N (1 ≤ N ≤ 100) cows, conveniently numbered 1..N, are participating in a programming con ...

  3. Graph Theory

    Description Little Q loves playing with different kinds of graphs very much. One day he thought abou ...

  4. c# 两个软件传参

    1.socket 传参,类似于小型的服务器和客户端,一端发送,另一端保持监听状态. 2.通过第三方  数据库或者文件.

  5. .mat转成.npy文件+Python(Pytorch)压缩裁剪图片

    需求:现有数据文件V1.mat,里面包含多个数据集,现需将里面的images数据集提取出来,然后进行压缩裁剪成指定大小 V1.mat数据集目录: 1.从mat文件中提取数据(使用Python) V1. ...

  6. AutoHotKey 快速入门

    AutoHotKey 是一个免费的键盘宏程序,可以用于配置键盘快捷键.鼠标事件 以及摇杆事件,还可以在输入文本的时候对文本进行扩展(自动补全) 第一个脚本 新建文件test.ahk并输入以下内容: ^ ...

  7. Spring事务管理Transaction

    Spring提供了许多内置事务管理器实现: DataSourceTransactionManager:位于org.springframework.jdbc.datasource包中,数据源事务管理器, ...

  8. ASP.NET MVC4计划任务实现方法(定时执行某个功能)

    系统中定时执行某个任务是比较常用的功能,如一个部门定期向上级部门上报数据是一个典型的例子,下面就简单说说在.net mvc中如何实现定时执行某个功能的方法. 1.首先修改Glocal.asax文件,在 ...

  9. pascal语言中学版整理

    P1:主菜单File中的Command shell选项,可以暂时退出Pascal,进入DOS提示符状态,但Pascal仍然驻留在内存中.输入命令exit即可返回Pascal. P3:Edit菜单中Un ...

  10. 1923: [Sdoi2010]外星千足虫

    1923: [Sdoi2010]外星千足虫 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1254  Solved: 799[Submit][Statu ...