BZOJ2815:[ZJOI2012]灾难(拓扑排序,LCA)
Description
阿米巴是小强的好朋友。
阿米巴和小强在草原上捉蚂蚱。小强突然想,如果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引发一系列的生态灾难。
学过生物的阿米巴告诉小强,草原是一个极其稳定的生态系统。如果蚂蚱灭绝了,小鸟照样可以吃别的虫子,所以一个物种的灭绝并不一定会引发重大的灾难。
我们现在从专业一点的角度来看这个问题。我们用一种叫做食物网的有向图来描述生物之间的关系:
一个食物网有N个点,代表N种生物,如果生物x可以吃生物y,那么从y向x连一个有向边。
这个图没有环。
图中有一些点没有连出边,这些点代表的生物都是生产者,可以通过光合作用来生存; 而有连出边的点代表的都是消费者,它们必须通过吃其他生物来生存。
如果某个消费者的所有食物都灭绝了,它会跟着灭绝。
我们定义一个生物在食物网中的“灾难值”为,如果它突然灭绝,那么会跟着一起灭绝的生物的种数。
举个例子:在一个草场上,生物之间的关系是:
如 
如果小强和阿米巴把草原上所有的羊都给吓死了,那么狼会因为没有食物而灭绝,而小强和阿米巴可以通过吃牛、牛可以通过吃草来生存下去。所以,羊的灾难值是1。但是,如果草突然灭绝,那么整个草原上的5种生物都无法幸免,所以,草的灾难值是4。
给定一个食物网,你要求出每个生物的灾难值。
Input
输入文件 catas.in 的第一行是一个正整数 N,表示生物的种数。生物从 1 标
号到 N。
接下来 N 行,每行描述了一个生物可以吃的其他生物的列表,格式为用空
格隔开的若干个数字,每个数字表示一种生物的标号,最后一个数字是 0 表示列
表的结束。
Output
输出文件catas.out包含N行,每行一个整数,表示每个生物的灾难值。
Sample Input
1 2 3
1 4 5
2 4 7
2 3 6
3 4 8
Sample Output
3 6
Solution
感谢zhhe0101学长orz的耐心讲解
我太菜了听了好久才懂
不过这个题的做法的确是十分精妙的
大体分三步:1、拓扑排序2、建树3、求树的前缀和
1、我们知道,一个生物死亡的条件是他的所有食物全部死亡
而且既然这个题说了没有环,那么就可以保证食物链等级鲜明
那么求这种图,我们很容易就可以想到拓扑排序了
2、我们建一棵树,让father[x]为x的父亲,意味着若father[x]死了,那么x则灭绝
问题来了,x应该挂在哪个点上?
当然是他所有食物的LCA上啊!
若LCA死了,x的食物也会都死亡,那么x也必然死亡
建树这里可以将出度为0的点连在一个虚拟点n+1上方便处理
3、最后DFS求一下树的前缀和
因为若x死了,那么他的子树会全部死亡,那么他的重要度就是子树大小-1(去除本身)
最后附样例转树的图(学长给我画的)
5 →2 →1
↗ ↗
4 →3
6
↓
1
↙↓↘
2 3 4
↙
5
Code
#include<iostream>
#include<cstdio>
#include<queue>
#define MAXN (65534+5)
using namespace std;
int head1[MAXN],head[MAXN],num1,num2;
int n,ind[MAXN],sum,topo[MAXN];
int father[MAXN],f[MAXN][],depth[MAXN];
int SUM[MAXN]; //1为拓扑序所用邻接表
//2为树所用邻接表
struct node1
{
int to,next;
}edge1[MAXN*];//这里不是很懂为什么要开MAXN*4……?
void add1(int u,int v)
{
edge1[++num1].to=v;
edge1[num1].next=head1[u];
head1[u]=num1;
}
struct node
{
int to,next;
}edge[MAXN*+];
void add(int u,int v)
{
edge[++num2].to=v;
edge[num2].next=head[u];
head[u]=num2;
} //toposort拓扑排序
//RMQ倍增做LCA的预处理
//LCA找两个点的最近公共祖先
//build将拓扑排序转换为一颗有根树
//DPtree求树上前缀和
void toposort()
{
queue<int>q;
for (int i=;i<=n;++i)
if(ind[i]==)
q.push(i); while (!q.empty())
{
int x=q.front();
q.pop();
topo[++sum]=x;
for (int i=head1[x];i!=;i=edge1[i].next)
{
ind[edge1[i].to]--;
if(!ind[edge1[i].to])
q.push(edge1[i].to);
}
}
}
void RMQ(int x)
{
f[x][]=father[x];
for (int i=;i<=;++i)
f[x][i]=f[f[x][i-]][i-];
}
int LCA(int x,int y)//x is under y
{
if (depth[x]<depth[y]) swap(x,y);
for (int i=;i>=;--i)
if (f[x][i]!=&&depth[f[x][i]]>=depth[y])
x=f[x][i];
if (x==y) return y;
for (int i=;i>=;--i)
if (f[x][i]!=&&f[y][i]!=&&f[x][i]!=f[y][i])
{
x=f[x][i];
y=f[y][i];
}
return father[x];
}
void build()
{
depth[n+]=;
father[n+]=n+;
for (int i=n;i>=;--i)
{
int x=topo[i];
if (head1[x]==)
{
father[x]=n+;
add(n+,x);
f[x][]=n+;
depth[x]=;
continue;
}
int lca=edge1[head1[x]].to;
for (int i=edge1[head1[x]].next;i!=;i=edge1[i].next)
{
lca=LCA(lca,edge1[i].to);
}
father[x]=lca;
add(father[x],x);
depth[x]=depth[father[x]]+;
RMQ(x);
}
}
void DPtree(int x)
{
SUM[x]=;
for (int i=head[x];i!=;i=edge[i].next)
{
DPtree(edge[i].to);
SUM[x]+=SUM[edge[i].to];
}
} //main函数
int main()
{
int x;
scanf("%d",&n);
for (int i=;i<=n;++i)
{
scanf("%d",&x);
while (x!=)
{
add1(i,x);
++ind[x];//食物入度+1
scanf("%d",&x);
}
}
toposort();//拓扑排序
build();//建树
DPtree(n+);
for (int i=;i<=n;++i)
printf("%d\n",SUM[i]-);
}
BZOJ2815:[ZJOI2012]灾难(拓扑排序,LCA)的更多相关文章
- 【BZOJ2815】[ZJOI2012]灾难 拓扑排序+LCA
[BZOJ2815][ZJOI2012]灾难 题目描述 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从 ...
- [BZOJ2815][ZJOI2012]灾难(拓扑排序/支配树)
支配树目前只见到这一个应用,那就不独分一类,直接作为拓扑排序题好了. 每个点向所有食物连边,定义fa[x]为x的支配点,即离x最近的点,满足若fa[x]灭绝,则x也要灭绝. 这样,将fa[x]向x连边 ...
- 【bzoj2815】[ZJOI2012]灾难 拓扑排序+倍增LCA
题目描述(转自洛谷) 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引发一系列的生态灾难. 学过生物 ...
- 【bzoj2815】灾难[ZJOI2012](拓扑排序+lca)
题目传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2815 原版题解:http://fanhq666.blog.163.com/blog/st ...
- 洛谷P2597 [ZJOI2012] 灾难 [拓扑排序,LCA]
题目传送门 灾难 题目描述 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,如果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引发一系列的生态灾难. ...
- P2597 [ZJOI2012]灾难 拓扑排序
这个题有点意思,正常写法肯定会T,然后需要优化.先用拓扑排序重构一遍树,然后进行一个非常神奇的操作:把每个点放在他的食物的lca上,然后计算的时候直接dfs全加上就行了.为什么呢,因为假如你的食物的l ...
- BZOJ 2815: [ZJOI2012]灾难 拓扑排序+倍增LCA
这种问题的转化方式挺巧妙的. Code: #include <bits/stdc++.h> #define N 100000 #define M 1000000 #define setIO ...
- [BZOJ2815][ZJOI2012]灾难 灭绝树+拓扑排序+lca
灾难 [问题描述] 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,如果蚂蚱被他们捉灭绝了,那 么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引发一系列的 生态灾难. 学过 ...
- 【题解】 [ZJOI2012]灾难 (拓扑排序+LCA)
懒得复制,戳我戳我 Solution: 这题思路很神奇,首先你要知道这个毁灭树是怎么保证实现的:一句话就是如果该节点要被破坏,他的所有父节点就要被破坏,也就只要所有父节点的LCA被破坏就可以,所以我们 ...
随机推荐
- 音频播放时出现 Uncaught (in promise) DOMException: play() failed because the user didn't interact with the document first. https://goo.gl/xX8pDD
<audio id="play" controls="controls" loop="loop"> <source src ...
- WIN7 下IIS7的rewrite伪静态功能设置方法
win7系统都自带有iis的功能.关于WIN7下IIS的安装,请参考这里 http://jingyan.baidu.com/article/219f4bf723bcb2de442d38ed.html ...
- 乐字节-Java8新特性之方法引用
上一篇小乐介绍了<Java8新特性-函数式接口>,大家可以点击回顾.这篇文章将接着介绍Java8新特性之方法引用. Java8 中引入方法引用新特性,用于简化应用对象方法的调用, 方法引用 ...
- 自己写一个java的mvc框架吧(五)
自己写一个mvc框架吧(五) 给框架添加注解的支持 一段废话 上一章本来是说这一章要写视图处理的部分,但是由于我在测试代码的时候需要频繁的修改配置文件,太麻烦了.所以这一章先把支持注解的功能加上,这样 ...
- RocketMQ 主从同步机制
主从同步(HA 高可用) 主从同步原理: 为了保证系统的高可用,消息到达主服务器后,需要将消息同步到从服务器.如果主服务器宕机,消费者可用从从服务器拉取消息. 大体步骤: 1.主服务器启动,监听从服务 ...
- python学习之老男孩python全栈第九期_day012知识点总结
# def wrapper(f):# def inner(*args,**kwargs):# print('在被装饰的函数执行之前做的事')# res = f(*args,**kwargs)# pri ...
- php实现同一时间内一个账户只允许在一个终端登陆
在账户表的基础上,我新建了一个账户account_session表,用来记录登录账户的account_id和最新一次登录成功用户的session_id,然后首先要修改登录方法:每次登录成功后,要将登录 ...
- org.springframework.web.util.NestedServletException Handler processing failed; n
因为谷歌的lists不支持或使用, 所有要改成java的list工具 谷歌list使用: import com.google.common.collect.Lists; .... Lists.newA ...
- bzoj1758Wc10重建计划——solution
1758: [Wc2010]重建计划 Time Limit: 40 Sec Memory Limit: 162 MBSubmit: 4707 Solved: 1200[Submit][Status ...
- h5向上翻页图标晃动动画,css固定h5向上翻页图标在页面上
//html结构<div class='upImg'><div> //css .upImg { background-image: url(../images/01.png); ...