洛谷 P2921 [USACO08DEC]在農場萬聖節Trick or Treat on the Farm

題目描述

每一年,在威斯康星州,奶牛們都會穿上衣服,收集農夫約翰在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個隔間。

輸入輸出樣例

輸入樣例#1: 複製
4 
1 
3 
2 
3 
輸出樣例#1: 複製
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 }
相關文章
相關標籤/搜索