bzoj 2815
http://www.cnblogs.com/JS-Shining/archive/2013/01/12/2857429.html 题面
题解上写了用什么dominator tree,吓晕了,看了看,好像看不懂,于是看了看hzwer的代码,发现和dominator tree无半点关系。
-----------------------------------------------------------------------------------------------------------------------------------
首先我们假设有一个太阳,就是所有没有食物的物种的食物。
然后我们想一下 如果一个物种要灭绝,那么他的食物得先灭绝。他的食物怎么会灭绝?那么他的食物的食物也得灭绝,最后这些食物的根源肯定会汇集到一个点上,也就是所有食物得lca(你想啊一棵树上几个点不断往上爬肯定会汇集到一个点上(其实我也不太懂))。首先我们得拓扑排序一下,因为拓扑排序让一个物种能处于他的食物以及食物的食物之后(之后是指顺序上,也就是保证先处理好了自己食物及食物得的食物等,再处理自己)。然后扫描拓扑排序后的物种,对于每个物种,找他食物的lca,如果原图中没有食物,我们搞的太阳就变成了它的食物,然后把这个物种放在lca下面。这棵树可以帮我们统计答案,因为树的节点的儿子都是这个节点灭绝后会导致灭绝的物种。为什么放在lca下可以呢?因为我们要找lca的目的在于找到哪个物种能让自己灭绝,又因为lca能让这个物种灭绝,所以放在下面是对的。如何统计答案呢?因为每个点下挂的节点都是自己的灭绝能让他也灭绝,自己的儿子也是这样,所以以每个节点的子树大小-1就是答案。-1是把自己减去。
(我的代码是不是跟hzwer的很像?因为我看了他的,深受影响)还说一个可能的问题,为什么两个图能共用一个e数组?因为他们的head不一样
#include<bits/stdc++.h>
using namespace std;
#define N 100010
struct edge
{
int nxt,to;
}e[N<<];
int n,cnt=;
vector<int> q,s;
struct G
{
int dep[N],head[N],size[N],in[N];
int fa[N][];
void init()
{
memset(fa,-,sizeof(fa));
}
void link(int u,int v)
{
e[++cnt].nxt=head[u];
head[u]=cnt;
e[cnt].to=v;
in[v]++;
}
int lca(int u,int v)
{
if(u==-) return v;
if(v==-) return u;
if(dep[u]<dep[v]) swap(u,v);
int temp=dep[u]-dep[v];
for(int i=;i>=;--i) if(temp&(<<i))
u=fa[u][i];
if(u==v) return u;
for(int i=;i>=;--i) if(fa[u][i]!=fa[v][i])
{
u=fa[u][i]; v=fa[v][i];
}
return fa[u][];
}
void dfs(int u)
{
size[u]=;
for(int i=head[u];i;i=e[i].nxt)
{
dfs(e[i].to);
size[u]+=size[e[i].to];
}
}
void tp()
{
for(int i=;i<=n;++i) if(!in[i]) q.push_back(i);
while(!q.empty())
{
int u=q.back(); q.pop_back(); s.push_back(u);
for(int i=head[u];i;i=e[i].nxt)
{
in[e[i].to]--;
if(!in[e[i].to]) q.push_back(e[i].to);
}
}
}
void update(int u)
{
for(int i=;i<=;++i) if(fa[u][i-])
fa[u][i]=fa[fa[u][i-]][i-];
}
}G1,G2;
void build_tree()
{
for(int i=s.size()-;i>=;--i)
{
int u=s[i],lca=-;
for(int j=G1.head[u];j;j=e[j].nxt)
lca=G2.lca(e[j].to,lca);
if(lca==-) lca=;
G2.link(lca,u);
G2.fa[u][]=lca;
G2.dep[u]=G2.dep[lca]+;
G2.update(u);
}
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;++i)
{
int x; scanf("%d",&x);
while(x)
{
G1.link(i,x);
scanf("%d",&x);
}
}
G1.tp();
build_tree();
G2.dfs();
for(int i=;i<=n;++i)
{
if(G2.size[i]) printf("%d\n",G2.size[i]-);
else puts("");
}
return ;
}
bzoj 2815的更多相关文章
- bzoj 2815 [ZJOI2012]灾难(构造,树形DP)
[题意] 求把每个点删除后,不可达点的数目. [思路] 构造一棵“灭绝树”,要求这棵树满足如果删除根节点后则该子树内的所有结点都不可达.则答案为子树大小-1. 如何构造这棵“灭绝树”? 将原图拓扑排序 ...
- bzoj 2815 灭绝树
对于一个食物网(一个DAG),一个物种死亡后,某些物种就必然死亡,求出必然死亡的是那些物种. 灭绝树的另一种含义是:“灭绝树跟节点到节点u的路径上的节点由那些原图中从根节点到节点u的所有路径中都经过了 ...
- 灾难 bzoj 2815
灾难(1s 128MB)catas [样例输入] 5 0 1 0 1 0 2 3 0 2 0 [样例输出] 4 1 0 0 0 题解: 主要算法:拓扑排序:最近公共祖先(Lca): 先跑出拓扑序 我们 ...
- BZOJ 2815: [ZJOI2012]灾难
呃,题面没了,大概就是给出一些生物之间的捕食关系,求灭绝树每个点的灾难值. 拓扑排序之后倒着加入点,动态维护fa[][]数组,倍增法求LCA,当然大佬愿意写动态树也是极好的…… #include &l ...
- bzoj 2815 灾难
首先假设我们定义x灭绝后y会灭绝,那么离y最近的x就为y的父亲节点,那么如果我们可以求出每个节点的父亲节点,我们就得到了一棵树,然后每个节点的灾难值就是子树的大小-1. 我们将出度数为0的节点的父亲节 ...
- BZOJ 2815: [ZJOI2012]灾难 拓扑排序+倍增LCA
这种问题的转化方式挺巧妙的. Code: #include <bits/stdc++.h> #define N 100000 #define M 1000000 #define setIO ...
- BZOJ2815: [ZJOI2012]灾难
传送门 学LCA的时候根本没意识到LCA可以有这么多玩法. 这玩意据说是个高级数据结构(支配树)的弱化版,蒟蒻没学过呀.所以出题人提出一个概念叫灾难树. 我理解的灾难树的意思实际上是属于DAG的一个子 ...
- Luogu 2597 [ZJOI2012]灾难
BZOJ 2815. 解法还是挺巧妙的. 放上写得很详细很好懂的题解链接 戳这里. 一个物种$x$如果要灭绝,那么沿着它的入边反向走走走,一定可以走到一个点$y$,如果这个点$y$的物种灭绝了,那么 ...
- 2815: [ZJOI2012]灾难 - BZOJ
题目描述 Description 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,如果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引发一系列的 ...
随机推荐
- 禁止ScrollView在子控件的布局改变时自动滚动的的方法
重写scrollview中的如下方法,并将其返回值设为0即可. @Override protected int computeScrollDeltaToGetChildRectOnScreen(Re ...
- gridview读取Excel文件中的数据,并将其导入数据库
原文发布时间为:2008-10-16 -- 来源于本人的百度文章 [由搬家工具导入] //将需要导入的文件上传到服务器 string filePath = "" ...
- SQL中distinct的用法(四种示例分析)
在使用mysql时,有时需要查询出某个字段不重复的记录,虽然mysql提供有distinct这个关键字来过滤掉多余的重复记录只保留一条,但往往只 用它来返回不重复记录的条数,而不是用它来返回不重记录的 ...
- x1 carbon 扩展屏 模糊
x1 carbon 扩展屏 模糊,扩展屏是dell的屏,分辨率最大是1920*1080, x1最大是2560*1440. 不论是通过DP mini转VGA,还是HDMI,输出都是模糊,只有复制屏幕的时 ...
- 创建SSH keys
1.检查是否已经有SSH Key存在 windows: type "%userprofile%\.ssh\id_rsa.pub" Linux: cat ~/.ssh/id_rsa. ...
- ACM-ICPC 2018 南京赛区网络预赛 L && BZOJ 2763 分层最短路
https://nanti.jisuanke.com/t/31001 题意 可以把k条边的权值变为0,求s到t的最短路 解析 分层最短路 我们建立k+1层图 层与层之间边权为0,i 向 i+1层转 ...
- linux C 中的volatile使用
一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了.精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存 ...
- HDU 4115 Eliminate the Conflict(2-sat)
HDU 4115 Eliminate the Conflict pid=4115">题目链接 题意:Alice和Bob这对狗男女在玩剪刀石头布.已知Bob每轮要出什么,然后Bob给Al ...
- linux core文件设置
http://blog.csdn.net/ctthuangcheng/article/details/8963551 linux core文件设置 分类: Linux OS Debugging Te ...
- 无限级分类Asp.net Mvc实现
无限级分类Asp.net Mvc实现 无限级分类涉及到异步加载子类.加载当前类和匹配问题,现在做一个通用的实现. (一) 效果如下: (二)设计.实现及使用 (1)数据库 (a)表设计db ...