[洛谷P2597] [ZJOI2012]灾难
洛谷题目链接:[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]灾难的更多相关文章
- 洛谷 P2597 [ZJOI2012]灾难 解题报告
P2597 [ZJOI2012]灾难 题目描述 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,如果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引发 ...
- 洛谷P2597 [ZJOI2012] 灾难 [拓扑排序,LCA]
题目传送门 灾难 题目描述 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,如果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引发一系列的生态灾难. ...
- [bzoj2815] [洛谷P2597] [ZJOI2012] 灾难
Description 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,如果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引发一系列的生态灾难. 学过 ...
- Solution -「ZJOI2012」「洛谷 P2597」灾难
\(\mathcal{Description}\) link. 给定一个捕食网络,对于每个物种,求其灭绝后有多少消费者失去所有食物来源.(一些名词与生物学的定义相同 w.) 原图结点数 \ ...
- P2597 [ZJOI2012]灾难——拓扑,倍增,LCA
最近想学支配树,但是基础还是要打好了的: P2597 [ZJOI2012]灾难 这道题是根据食物链链接出一个有向图的关系,求一个物种的灭绝会连带几种物种的灭绝: 求得就是一个点能支配几个点: 如果一个 ...
- [洛谷P2610] [ZJOI2012]旅游
洛谷题目链接:[ZJOI2012]旅游 题目描述 到了难得的暑假,为了庆祝小白在数学考试中取得的优异成绩,小蓝决定带小白出去旅游~~ 经过一番抉择,两人决定将T国作为他们的目的地.T国的国土可以用一个 ...
- 【洛谷 P2597】 [ZJOI2012]灾难(LCA)
题目链接 考虑建一棵树,使一个生物灭绝时他的子树都会灭绝,显然这样答案就是以每个点为根的子树大小-1. 为什么原图不是一棵树,因为一个生物可能会以多个生物为食,所以按拓扑序来建树,把每个遍历到的点的父 ...
- 洛谷 P2611 [ZJOI2012]小蓝的好友 解题报告
P2611 [ZJOI2012]小蓝的好友 题目描述 终于到达了这次选拔赛的最后一题,想必你已经厌倦了小蓝和小白的故事,为了回馈各位比赛选手,此题的主角是贯穿这次比赛的关键人物--小蓝的好友. 在帮小 ...
- P2597 [ZJOI2012]灾难
\(\color{#0066ff}{ 题目描述 }\) 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,如果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝, ...
随机推荐
- protected、public、private
一.protected成员 1. 受保护的成员的可访问性 对于一个类的protected成员,①该类的用户(如类对象)不能访问它,②该类的派生类的成员(及其友元)可以访问它. 派生类的成员及其友元不能 ...
- 无法启动mysql服务 错误1067:进程意外中止
这个错误在前些周遇到过,没有解决,直接粗暴的卸载重装了,自己用的是wampserver集成环境,重装的后果是mysql里面的一些已有的数据库就没有了,有点小悲剧,不过幸好都是一些测试用的数据库,后面直 ...
- lintcode-142-O(1)时间检测2的幂次
142-O(1)时间检测2的幂次 用 O(1) 时间检测整数 n 是否是 2 的幂次. 样例 n=4,返回 true; n=5,返回 false. 挑战 O(1) time 标签 比特位操作 思路 使 ...
- iOS- iOS 7 的后台多任务 (Multitasking) 对比之前的异同、具体机制、变化
简单来说,这玩意是对开发者友好,但对设备不友好的(可能会偷偷摸摸地占用流量和电量).对用户来说,如果你带宽够,对发热不敏感的话,会得到更好的应用体验. 从 iOS 4 开始,应用就可以在退到后台后,继 ...
- RXSwift --UITableView之初探
对于RXSwift中的一些基本概念和说明请参看其他文章,接下来我们使用RXSwift一步一步去构建TableView,从简单到复杂.iOS开发过程中tableView的使用率是最高的,他的一些代理方法 ...
- arcgis api for javascript 各个版本的SDK下载
1.首先,进入下载网站,需要登录才能下载.下载链接 2.选择需要下载的版本,进行下载.
- 3dContactPointAnnotationTool开发日志(十)
要是那几个状态栏不能拖动的话岂不是显得太呆板了,于是我又参考Unity官方视频教程学习了如何实现拖动状态栏的功能,还挺简单的. 比如说要拖动这个PanelStatus面板,我只让使用者通过拖动 ...
- 制作QQ微信支付宝三合一收款码
转载:http://blog.mambaxin.com/article/56 发现很多博客都带了打赏功能,虽说打赏的人可能很少,但始终是一份心意,能让博主知道自己写的文章有用,能够帮助到人.所以,我也 ...
- perf 是怎么计算调用栈的时间的?
在我真个malloc的执行过程中共调用了8次的syswrite的系统调用,其中有两次来自于__lib_write, 两次来自于__memmove_avx_unaligned,然后__memmove_a ...
- [剑指Offer] 57.二叉树的下一个结点
题目描述 给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回.注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针. /* struct TreeLinkNode { in ...