博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[支配树] Bzoj P2815 灾难
阅读量:5262 次
发布时间:2019-06-14

本文共 2534 字,大约阅读时间需要 8 分钟。

题目描述

阿米巴是小强的好朋友。

阿米巴和小强在草原上捉蚂蚱。小强突然想,如果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引发一系列的生态灾难。

学过生物的阿米巴告诉小强,草原是一个极其稳定的生态系统。如果蚂蚱灭绝了,小鸟照样可以吃别的虫子,所以一个物种的灭绝并不一定会引发重大的灾难。

我们现在从专业一点的角度来看这个问题。我们用一种叫做食物网的有向图来描述生物之间的关系:

一个食物网有N个点,代表N种生物,如果生物x可以吃生物y,那么从y向x连一个有向边。

这个图没有环。

图中有一些点没有连出边,这些点代表的生物都是生产者,可以通过光合作用来生存; 而有连出边的点代表的都是消费者,它们必须通过吃其他生物来生存。

如果某个消费者的所有食物都灭绝了,它会跟着灭绝。

我们定义一个生物在食物网中的“灾难值”为,如果它突然灭绝,那么会跟着一起灭绝的生物的种数。

举个例子:在一个草场上,生物之间的关系是:

如 

如果小强和阿米巴把草原上所有的羊都给吓死了,那么狼会因为没有食物而灭绝,而小强和阿米巴可以通过吃牛、牛可以通过吃草来生存下去。所以,羊的灾难值是1。但是,如果草突然灭绝,那么整个草原上的5种生物都无法幸免,所以,草的灾难值是4。

给定一个食物网,你要求出每个生物的灾难值。

输入输出格式

输入格式:

 

输入文件 catas.in 的第一行是一个正整数 N,表示生物的种数。生物从 1 标

号到 N。

接下来 N 行,每行描述了一个生物可以吃的其他生物的列表,格式为用空

格隔开的若干个数字,每个数字表示一种生物的标号,最后一个数字是 0 表示列

表的结束。

 

输出格式:

 

输出文件catas.out包含N行,每行一个整数,表示每个生物的灾难值。

 

输入输出样例

输入样例#1: 
501 01 02 3 02 0
输出样例#1: 
41000

说明

【样例说明】

样例输入描述了题目描述中举的例子。

【数据规模】

对50%的数据,N ≤ 10000。

对100%的数据,1 ≤ N ≤ 65534。

输入文件的大小不超过1M。保证输入的食物网没有环。

 

 

题解

  • 直接把支配树建出来,然后一个点的答案就是它在支配树上的size-1

代码

1 #include 
2 #include
3 #include
4 #include
5 using namespace std; 6 const int N=100010; 7 int n,cnt,last[N],head[N],a[N],fa[N][20],deep[N],d[N],size[N]; 8 struct edge{
int to,from;}e[N*30]; 9 queue
Q;10 void insert(int x,int y)11 {12 e[++cnt].to=y,e[cnt].from=head[x],head[x]=cnt;13 e[++cnt].to=x,e[cnt].from=last[y],last[y]=cnt;14 }15 void topusort()16 {17 Q.push(n+1);18 while (!Q.empty()) 19 {20 int u=Q.front(); Q.pop(),a[++a[0]]=u;21 for (int i=head[u];i;i=e[i].from)22 {23 d[e[i].to]--;24 if (!d[e[i].to]) Q.push(e[i].to);25 }26 }27 }28 int getlca(int x,int y)29 {30 if (deep[x]
=0;i--) if (deep[fa[x][i]]>=deep[y]) x=fa[x][i];32 if (x==y) return x;33 for (int i=16;i>=0;i--) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];34 return fa[x][0];35 }36 int main()37 {38 scanf("%d",&n);39 for (int i=1,x;i<=n;i++) 40 {41 scanf("%d",&x);42 while (x) insert(x,i),scanf("%d",&x),d[i]++;43 }44 for (int i=1;i<=n;i++) if (!d[i]) insert(n+1,i),d[i]++;45 topusort();46 for (int i=1;i<=n+1;i++)47 {48 int x=a[i],y=0;49 for (int j=last[x];j;j=e[j].from) if (!y) y=e[j].to; else y=getlca(e[j].to,y);50 fa[x][0]=y,deep[x]=deep[y]+1;51 for (int j=1;j<=16;j++) fa[x][j]=fa[fa[x][j-1]][j-1];52 }53 for (int i=n+1;i>=1;i--) size[a[i]]++,size[fa[a[i]][0]]+=size[a[i]];54 for (int i=1;i<=n;i++) printf("%d\n",size[i]-1);55 }

 

转载于:https://www.cnblogs.com/Comfortable/p/11192853.html

你可能感兴趣的文章
Linux重定向: > 和 &> 区别
查看>>
nginx修改内核参数
查看>>
C 筛选法找素数
查看>>
TCP为什么需要3次握手与4次挥手(转载)
查看>>
IOC容器
查看>>
Windows 2003全面优化
查看>>
URAL 1002 Phone Numbers(KMP+最短路orDP)
查看>>
web_day4_css_宽度
查看>>
electron入门心得
查看>>
格而知之2:UIView的autoresizingMask属性探究
查看>>
我的Hook学习笔记
查看>>
js中的try/catch
查看>>
寄Android开发Gradle你需要知道的知识
查看>>
简述spring中常有的几种advice?
查看>>
整理推荐的CSS属性书写顺序
查看>>
ServerSocket和Socket通信
查看>>
css & input type & search icon
查看>>
源代码的下载和编译读后感
查看>>
Kafka学习笔记
查看>>
Octotree Chrome安装与使用方法
查看>>