[洛谷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}{ 题目描述 }\) 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,如果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝, ...
随机推荐
- spring 国际化i18n配置
i18n(其来源是英文单词 internationalization的首末字符i和n,18为中间的字符数)是“国际化”的简称.在资讯领域,国际化(i18n)指让产品(出版物,软件,硬件等)无需做大的改 ...
- 【IdentityServer4文档】- 贡献
贡献 我们非常乐于接受社区贡献,但您应遵循一些指导原则,以便我们可以很方便的解决这个问题. 如何贡献? 最简单的方法是打开一个问题并开始讨论.然后,我们可以决定如何实现一个特性或一个变更.如果您即将提 ...
- C# 如何在winform中嵌入Excel,内嵌Excel,word
近使用.net做一个小软件遇到一个问题,就是想实现把excel表格在winform中打开,同时可以操作,不单单是打开.或者就提取数据.在网上找了好多资料,发现这方面的资料比较少,即使有,都是旧版本的使 ...
- 【Docker 命令】- top命令
docker top :查看容器中运行的进程信息,支持 ps 命令参数. 语法 docker top [OPTIONS] CONTAINER [ps OPTIONS] 容器运行时不一定有/bin/ba ...
- 向今天要结果; 向明天要动力 eclipse不自动弹出提示(alt+/快捷键失效)
最近公司电脑上的Eclipse没有了自动提示功能,也不是全部不提示,大多数情况下按下“alt+/”键还会产生提示,但是当我在java项目中邪main方法和syso的时候,“alt+/”则会失效,今天在 ...
- idea超炫的自定义模板
idea超炫的自定义模板 idea 有些快捷键 sout -> System.out.println() ,输入sout,idea能自动补全代码, 这种约定的快捷方式大大提高了效率, 而id ...
- 【Python】PYTHON中STRIP()方法学习笔记
Python strip() 方法用于移除字符串头尾指定的字符(默认为空格). 当使用strip('xxx'),只要字符串头尾有"xxx"中的一个,就会去掉,而不是符合字符串''x ...
- 使用getRequestDispatcher跳转后 能获取到request.setAttribute数据 分析
- Swift学习与复习
swift中文网 http://www.swiftv.cn http://swifter.tips/ http://objccn.io/ http://www.swiftmi.com/code4swi ...
- Java入门之:对象和类
Java对象和类 Java作为一种面向对象语言,支持以下基本概念: 多态 继承 封装 抽象 类 对象 实例 方法 重载 本节我们重点研究对象和类的概念: 对象: 对象是类的一个实例,有状态和行为.例如 ...