题目描述
阿米巴是小强的好朋友。
阿米巴和小强在草原上捉蚂蚱。小强突然想,如果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引发一系列的生态灾难。
学过生物的阿米巴告诉小强,草原是一个极其稳定的生态系统。如果蚂蚱灭绝了,小鸟照样可以吃别的虫子,所以一个物种的灭绝并不一定会引发重大的灾难。
我们现在从专业一点的角度来看这个问题。我们用一种叫做食物网的有向图来描述生物之间的关系:
一个食物网有N个点,代表N种生物,如果生物x可以吃生物y,那么从y向x连一个有向边。
这个图没有环。
图中有一些点没有连出边,这些点代表的生物都是生产者,可以通过光合作用来生存; 而有连出边的点代表的都是消费者,它们必须通过吃其他生物来生存。
如果某个消费者的所有食物都灭绝了,它会跟着灭绝。
我们定义一个生物在食物网中的“灾难值”为,如果它突然灭绝,那么会跟着一起灭绝的生物的种数。
举个例子:在一个草场上,生物之间的关系是:
如
如果小强和阿米巴把草原上所有的羊都给吓死了,那么狼会因为没有食物而灭绝,而小强和阿米巴可以通过吃牛、牛可以通过吃草来生存下去。所以,羊的灾难值是1。但是,如果草突然灭绝,那么整个草原上的5种生物都无法幸免,所以,草的灾难值是4。
给定一个食物网,你要求出每个生物的灾难值。
输入输出格式
输入格式:
输入文件 catas.in 的第一行是一个正整数 N,表示生物的种数。生物从 1 标
号到 N。
接下来 N 行,每行描述了一个生物可以吃的其他生物的列表,格式为用空
格隔开的若干个数字,每个数字表示一种生物的标号,最后一个数字是 0 表示列
表的结束。
输出格式:
输出文件catas.out包含N行,每行一个整数,表示每个生物的灾难值。
输入输出样例
501 01 02 3 02 0
41000
说明
【样例说明】
样例输入描述了题目描述中举的例子。
【数据规模】
对50%的数据,N ≤ 10000。
对100%的数据,1 ≤ N ≤ 65534。
输入文件的大小不超过1M。保证输入的食物网没有环。
题解
- 直接把支配树建出来,然后一个点的答案就是它在支配树上的size-1
代码
1 #include2 #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 }