【BZOJ2815】【ZJOI2012】灾难 [LCA]
2017-02-21 15:48
246 查看
灾难
Time Limit: 10 Sec Memory Limit: 128 MB[Submit][Status][Discuss]
Description
阿米巴是小强的好朋友。
阿米巴和小强在草原上捉蚂蚱。小强突然想,如果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引发一系列的生态灾难。
学过生物的阿米巴告诉小强,草原是一个极其稳定的生态系统。如果蚂蚱灭绝了,小鸟照样可以吃别的虫子,所以一个物种的灭绝并不一定会引发重大的灾难。
我们现在从专业一点的角度来看这个问题。我们用一种叫做食物网的有向图来描述生物之间的关系:
一个食物网有 N个点,代表 N 种生物,如果生物 x 可以吃生物 y,那么从 y 向 x 连一个有向边。
这个图没有环。
图中有一些点没有连出边,这些点代表的生物都是生产者,可以通过光合作用来生存; 而有连出边的点代表的都是消费者,它们必须通过吃其他生物来生存。
如果某个消费者的所有食物都灭绝了,它会跟着灭绝。
我们定义一个生物在食物网中的“灾难值”为,如果它突然灭绝,那么会跟着一起灭绝的生物的种数。
举个例子:在一个草场上,生物之间的关系是:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> using namespace std; const int ONE=500001; const int INF=2147483640; int n,m,x; int f[ONE][22],Dep[ONE]; int next1[ONE],first1[ONE],go1[ONE],Input[ONE],tot1; int next[ONE],first[ONE],go[ONE],tot; int q[ONE],tou,wei; int size[ONE]; int get() { int res,Q=1; char c; while( (c=getchar())<48 || c>57) if(c=='-')Q=-1; if(Q) res=c-48; while((c=getchar())>=48 && c<=57) res=res*10+c-48; return res*Q; } int Add(int u,int v) { next1[++tot1]=first1[u]; first1[u]=tot1; go1[tot1]=v; Input[v]++; } int New_edge(int u,int v) { next[++tot]=first[u]; first[u]=tot; go[tot]=v; } int LCA(int x,int y) { if(x<0) return y; if(Dep[x]<Dep[y]) swap(x,y); for(int i=20;i>=0;i--) { if(Dep[f[x][i]]>=Dep[y]) x=f[x][i]; if(x==y) return x; } for(int i=20;i>=0;i--) { if(f[x][i]!=f[y][i]) { x=f[x][i]; y=f[y][i]; } } return f[x][0]; } void Topo() { tou=wei=0; for(int u=1;u<=n;u++) if(!Input[u]) q[++wei]=u; while(tou<wei) { int u=q[++tou]; for(int e=first1[u];e;e=next1[e]) { int v=go1[e]; if(!(--Input[v])) q[++wei]=v; } } } void Rebuild() { for(int i=wei;i>=1;i--) { int u=q[i]; int To=-INF; for(int e=first1[u];e;e=next1[e]) { int v=go1[e]; To=LCA(To,v); } int v=max(To,0); New_edge(v,u); Dep[u]=Dep[v]+1; f[u][0]=v; for(int i=0;i<=19;i++) { f[u][i+1]=f[f[u][i]][i]; } } } int Dfs(int u) { size[u]=1; for(int e=first[u];e;e=next[e]) { int v=go[e]; Dfs(v); size[u]+=size[v]; } } int main() { n=get(); for(int i=1;i<=n;i++) { for(;;) { x=get(); if(!x) break; Add(i,x); } } Topo(); Rebuild(); Dfs(0); for(int i=1;i<=n;i++) printf("%d\n",size[i]-1); }View Code
相关文章推荐
- BZOJ_2815_[ZJOI2012]灾难 倍增lca + 构造
- [BZOJ2815][ZJOI2012]灾难(倍增lca+top)
- bzoj 2815: [ZJOI2012]灾难|倍增lca|思路题
- 【ZJOI2012】【BZOJ2815】灾难 (catas) {拓扑+倍增lca}
- [拓扑+LCA]BZOJ 2815——[ZJOI2012]灾难
- 【BZOJ2815】【ZJOI2012】灾难 阿米巴和小强题 动态倍增LCA 灾难树
- BZOJ 2815 ZJOI 2012 灾难 动态倍增LCA
- 【bzoj2815】灾难[ZJOI2012](拓扑排序+lca)
- [BZOJ2815][ZJOI2012]灾难(拓扑排序+LCA)
- Lengauer-Tarjan算法--支配树构造(bzoj 2815: [ZJOI2012]灾难)
- 【BZOJ2815】灾难(ZJOI2012)-拓扑排序+建树+LCA
- [BZOJ2815][ZJOI2012]灾难 拓扑排序+lca
- [BZOJ2815][ZJOI2012]灾难 灭绝树+拓扑排序+lca
- BZOJ 2815: [ZJOI2012]灾难
- 2815: [ZJOI2012]灾难 - BZOJ
- bzoj 2815: [ZJOI2012]灾难
- [BZOJ2815][ZJOI2012]灾难-灭绝树
- bzoj 2815: [ZJOI2012]灾难
- 【BZOJ】2815: [ZJOI2012]灾难
- bzoj 2815 [ZJOI2012]灾难(构造,树形DP)