每一年,在威斯康星州,奶牛們都會穿上衣服,收集農夫約翰在N(1<=N<=100,000)個牛棚隔間中留下的糖果,以此來慶祝美國秋天的萬聖節。ios
因爲牛棚不太大,FJ經過指定奶牛必須遵循的穿越路線來確保奶牛的樂趣。爲了實現這個讓奶牛在牛棚裏來回穿梭的方案,FJ在第i號隔間上張貼了一個「下一個隔間」Next_i(1<=Next_i<=N),告訴奶牛要去的下一個隔間;這樣,爲了收集它們的糖果,奶牛就會在牛棚裏來回穿梭了。spa
FJ命令奶牛i應該從i號隔間開始收集糖果。若是一隻奶牛回到某一個她已經去過的隔間,她就會中止收集糖果。code
在被迫中止收集糖果以前,計算一下每頭奶牛要前往的隔間數(包含起點)。blog
第1行 整數n。string
第2行到n+1行 每行包含一個整數 next_i 。io
n行,第i行包含一個整數,表示第i只奶牛要前往的隔間數。class
有4個隔間stream
隔間1要求牛到隔間1搜索
隔間2要求牛到隔間3im
隔間3要求牛到隔間2
隔間4要求牛到隔間3
牛1,從1號隔間出發,總共訪問1個隔間;
牛2,從2號隔間出發,而後到三號隔間,而後到2號隔間,終止,總共訪問2個隔間;
牛3,從3號隔間出發,而後到2號隔間,而後到3號隔間,終止,總共訪問2個隔間;
牛4,從4號隔間出發,而後到3號隔間,而後到2號隔間,而後到3號隔間,終止,總共訪問3個隔間。
4 1 3 2 3
1 2 2 3
原本覺得是水題,被洛谷坑了2333。
若是暴力模擬能夠拿40分,以後想到記憶化搜索。
記憶化搜索對於樹是很是方便的,但沒法處理環,那就先tarjan縮點。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<stack> 5 using namespace std; 6 const int N=100005; 7 int n,tim,dcnt,next[N],nxt[N],dfn[N],low[N],belong[N],sz[N],ans[N]; 8 bool instk[N],vis[N]; 9 stack<int>stk; 10 void tarjan(int u) 11 { 12 dfn[u]=low[u]=++tim; 13 instk[u]=1; 14 stk.push(u); 15 if(next[u]) 16 { 17 if(dfn[next[u]]==0) 18 { 19 tarjan(next[u]); 20 low[u]=min(low[u],low[next[u]]); 21 } 22 else if(instk[next[u]]) 23 low[u]=min(low[u],dfn[next[u]]); 24 } 25 if(low[u]==dfn[u]) 26 { 27 ++dcnt; 28 while(1) 29 { 30 int t=stk.top(); 31 stk.pop(); 32 instk[t]=0; 33 belong[t]=dcnt; 34 sz[dcnt]++; 35 if(t==u) 36 break; 37 } 38 } 39 } 40 void dfs(int u) 41 { 42 if(nxt[u]) 43 { 44 if(!vis[nxt[u]]) 45 { 46 dfs(nxt[u]); 47 vis[nxt[u]]=1; 48 } 49 ans[u]=ans[nxt[u]]+sz[u]; 50 } 51 else 52 { 53 ans[u]=sz[u]; 54 vis[u]=1; 55 } 56 } 57 int main() 58 { 59 scanf("%d",&n); 60 for(int i=1;i<=n;i++) 61 { 62 scanf("%d",&next[i]); 63 if(next[i]==i) 64 next[i]=0; 65 } 66 for(int i=1;i<=n;i++) 67 if(!dfn[i]) 68 tarjan(i); 69 for(int i=1;i<=n;i++) 70 if(next[i]&&belong[i]!=belong[next[i]]) 71 nxt[belong[i]]=belong[next[i]]; 72 for(int i=1;i<=dcnt;i++) 73 if(!vis[i]) 74 { 75 dfs(i); 76 vis[i]=1; 77 } 78 for(int i=1;i<=n;i++) 79 printf("%d\n",ans[belong[i]]); 80 return 0; 81 }