1. 程式人生 > >bzoj 1589: [Usaco2008 Dec]Trick or Treat on the Farm 采集糖果

bzoj 1589: [Usaco2008 Dec]Trick or Treat on the Farm 采集糖果

lap size cstring stk 采集 pri out pla reat

Description

每年萬聖節,威斯康星的奶牛們都要打扮一番,出門在農場的N(1≤N≤100000)個牛棚裏轉悠,來采集糖果.她們每走到一個未曾經過的牛棚,就會采集這個棚裏的1顆糖果. 農場不大,所以約翰要想盡法子讓奶牛們得到快樂.他給每一個牛棚設置了一個“後繼牛棚”.牛棚i的後繼牛棚是Xi.他告訴奶牛們,她們到了一個牛棚之後,只要再往後繼牛棚走去,就可以搜集到很多糖果.事實上這是一種有點欺騙意味的手段,來節約他的糖果. 第i只奶牛從牛棚i開始她的旅程.請你計算,每一只奶牛可以采集到多少糖果.

Input

第1行輸入N,之後一行一個整數表示牛棚i的後繼牛棚Xi,共N行.

Output

共N行,一行一個整數表示一只奶牛可以采集的糖果數量.

Sample Input

4 //有四個點
1 //1有一條邊指向1
3 //2有一條邊指向3
2 //3有一條邊指向2
3

INPUT DETAILS:

Four stalls.
* Stall 1 directs the cow back to stall 1.
* Stall 2 directs the cow to stall 3
* Stall 3 directs the cow to stall 2
* Stall 4 directs the cow to stall 3

Sample Output

1
2
2
3
———————————————————————— 這道題就是求一個點到他指向的環的距離+環的大小 所以拓撲排序求一下環 然後根據拓撲的隊列倒著求一波答案 技術分享
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int M=150007;
int read(){
    int ans=0,f=1,c=getchar();
    while(c<0||c>9){if(c==-) f=-1; c=getchar();}
    
while(c>=0&&c<=9){ans=ans*10+(c-0); c=getchar();} return ans*f; } int n,to[M],in[M],stk[M],top,f[M]; int head,tail,q[M]; int main(){ n=read(); for(int i=1;i<=n;i++) to[i]=read(),in[to[i]]++; for(int i=1;i<=n;i++) if(!in[i]) q[tail++]=i; while(head<=tail){ int x=q[head++],now=to[x]; in[now]--; if(!in[now]) q[tail++]=now; } for(int i=1;i<=n;i++)if(in[i]){ int now=i,h=1; stk[top=1]=i; in[i]=0; while(1){ now=to[now]; if(now==i) break; h++; in[now]=0; stk[++top]=now; } while(top) f[stk[top]]=h,top--; } while(tail>0) tail--,f[q[tail]]=f[to[q[tail]]]+1; for(int i=1;i<=n;i++) printf("%d\n",f[i]); return 0; }
View Code

bzoj 1589: [Usaco2008 Dec]Trick or Treat on the Farm 采集糖果