[ZJOI2012] 灾难
2018-03-29 09:09
162 查看
题目描述:
雾.题目分析:
本题出题人题解:http://fanhq666.blog.163.com/blog/static/8194342620124274154996/有这样一个事实:
生物之间的灭绝的结构形成了一个树,树上的一个节点的灭绝会且仅会导致以它为根的子树的灭绝。我们管这个树叫“灭绝树”。
对于生产者,我们给它添加一个假想的食物:太阳。
这样,“灭绝树”就形成了一个以太阳为根的树。
下面说明如何通过增量法把灭绝树建出来,同时也是对灭绝树的存在性的证明。
首先,把食物网按从猎物到捕食者的顺序拓扑排序。
之后,依次考虑每个生物i.我们已经构建好了排序在i之前的生物组成的“灭绝树”了。
假设i的食物有x[0]~x[k](x[0]~x[k]在拓扑排序中比i靠前)。
很显然,只有x[0]~x[k]在树上的公共祖先的灭绝会导致i灭绝,否则i一定可以找到能让它活下来的食物。
...
/
/
LCA
/|\
_/ ||
/ | \
O | \
/ \ \ \
x x x x
i
于是,我们可以把i挂在x[0]~x[k]的最近公共祖先下面。
处理完所有的生物,我们得到的树就是整个图的灭绝树了。
一旦得到灭绝树,每个生物的灾难值就可以通过以它为根的子树的大小减1来计算.
题目链接:
Luogu 2597Ac 代码:
#include <iostream> #include <cstdio> #include <algorithm> #include <queue> #define cnt Cnt[f] const int maxm=65540; int siz[maxm],son[maxm],top[maxm],fax[maxm],deep[maxm],f[maxm][17]; int head[2][maxm],to[2][maxm<<2],net[2][maxm<<2],Cnt[2]; int r[maxm],topdl[maxm]; std::queue<int> dl; int ans[maxm],n; inline void addedge(int x,int y,bool f) { to[f][++cnt]=y; net[f][cnt]=head[f][x],head[f][x]=cnt; } inline int LCA(int x,int y) { if(deep[x]<deep[y]) std::swap(x,y); for(int i=16;i>=0;i--) if(f[x][i]&&deep[f[x][i]]>deep[y]) x=f[x][i]; if(x==y) return y; for(int i=16;i>=0;i--) if(f[x][i]&&f[y][i]&&f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i]; return fax[x]; } inline void addst(int x) { f[x][0]=fax[x]; for(int i=1;i<=16;i++) f[x][i]=f[f[x][i-1]][i-1]; } inline void topsort() { int now=0; for(int i=1;i<=n;i++) if(!r[i]) dl.push(i); while(!dl.empty()) { int x=dl.front(); dl.pop(); topdl[++now]=x; for(int i=head[0][x];i;i=net[0][i]) { int tmp=to[0][i]; r[tmp]--; if(!r[tmp]) dl.push(tmp); } } } inline void makemap() { topsort(); deep[n+1]=1,fax[n+1]=n+1; for(int i=n;i>=1;i--) { int x=topdl[i]; if(!head[0][x]) { fax[x]=n+1,deep[x]=2; addedge(n+1,x,1); f[x][0]=n+1; continue; } int lca=to[0][head[0][x]]; for(int j=net[0][head[0][x]];j;j=net[0][j]) { int tmp=to[0][j]; lca=LCA(lca,tmp); } fax[x]=lca,deep[x]=deep[lca]+1; addedge(lca,x,1); addst(x); } } void dfs(int now) { ans[now]=1; for(int i=head[1][now];i;i=net[1][i]) { int tmp=to[1][i]; dfs(tmp); ans[now]+=ans[tmp]; } } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { int x; while(1) { scanf("%d",&x); if(!x) break; addedge(i,x,0); r[x]++; } } makemap(); dfs(n+1); for(int i=1;i<=n;i++) printf("%d\n",ans[i]-1); return 0; }
相关文章推荐
- 【bzoj2851】【ZJOI2012】【灾难】【LCA】
- bzoj2815: [ZJOI2012]灾难
- 2815: [ZJOI2012]灾难
- 【BZOJ2815】灾难(ZJOI2012)-拓扑排序+建树+LCA
- [BZOJ2815][ZJOI2012]灾难-灭绝树
- [BZOJ2815][ZJOI2012]灾难(倍增lca+top)
- 【ZJOI2012】【BZOJ2815】灾难 (catas) {拓扑+倍增lca}
- BZOJ 2815: [ZJOI2012]灾难
- 【bzoj2815】灾难[ZJOI2012](拓扑排序+lca)
- BZOJ 2815: [ZJOI2012]灾难
- [BZOJ2815][ZJOI2012]灾难(拓扑排序+LCA)
- 【bzoj2815】[ZJOI2012]灾难 拓扑排序+倍增LCA
- [ZJOI 2012]灾难
- 【BZOJ2815】【ZJOI2012】灾难 阿米巴和小强题 动态倍增LCA 灾难树
- BZOJ2815 [ZJOI2012]灾难
- 【BZOJ2815】[ZJOI2012]灾难 拓扑排序+LCA
- [拓扑+LCA]BZOJ 2815——[ZJOI2012]灾难
- Lengauer-Tarjan算法--支配树构造(bzoj 2815: [ZJOI2012]灾难)
- [BZOJ2815][ZJOI2012]灾难 灭绝树+拓扑排序+lca
- [ZJOI2012]灾难