[USACO08DEC] Trick or Treat on the Farm
Posted Zoewilly
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[USACO08DEC] Trick or Treat on the Farm相关的知识,希望对你有一定的参考价值。
题目描述
每年万圣节,威斯康星的奶牛们都要打扮一番,出门在农场的N个牛棚里转 悠,来采集糖果.她们每走到一个未曾经过的牛棚,就会采集这个棚里的1颗糖果.
农场不大,所以约翰要想尽法子让奶牛们得到快乐.他给每一个牛棚设置了一个“后继牛 棚”.牛棚i的后继牛棚是next_i 他告诉奶牛们,她们到了一个牛棚之后,只要再往后继牛棚走去, 就可以搜集到很多糖果.事实上这是一种有点欺骗意味的手段,来节约他的糖果.
第i只奶牛从牛棚i开始她的旅程.请你计算,每一只奶牛可以采集到多少糖果.
输入输出格式
输入格式:
-
Line 1: A single integer: N
- Lines 2..N+1: Line i+1 contains a single integer: next_i
输出格式:
- Lines 1..N: Line i contains a single integer that is the total number of unique stalls visited by cow i before she returns to a stall she has previously visited.
输入输出样例
4 1 3 2 3
1 2 2 3
说明
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
Cow 1: Start at 1, next is 1. Total stalls visited: 1.
Cow 2: Start at 2, next is 3, next is 2. Total stalls visited: 2. Cow 3: Start at 3, next is 2, next is 3. Total stalls visited: 2. Cow 4: Start at 4, next is 3, next is 2, next is 3. Total stalls visited: 3.
- 本题n<=100000,首先考虑记忆化搜索,因为纯搜索在某些极端情况一定会被卡(n^2)。
- 但是记忆化搜索怎么实现呢?
- 通过观察样例发现,本题存在环。
- tarjan缩点+记忆化搜索。(大神说不用tarjan)。
- 所有环上的点的答案即为该环的长度,其余的点呢?因为其他的点都是指向某个环的,所以记忆化搜索即可(dp)。
- 期望得分100分。
1 #include <cstdio> 2 #include <algorithm> 3 #include <iostream> 4 #define time dscada 5 using namespace std; 6 7 int n,l,cnt,top,next[100050],summ[100050],pre[100050],time,last[100050],other[100050],f[100050],dfn[100050],low[100050],stack[100050],huan[100050]; 8 bool cir[100050],vis[100050]; 9 10 void add(int u,int v) { 11 pre[++l]=last[u]; 12 last[u]=l; 13 other[l]=v; 14 } 15 16 void tarjan(int x) { 17 dfn[x]=low[x]=++time; 18 stack[++top]=x; 19 vis[x]=1; 20 for (int p=last[x]; p; p=pre[p]) { 21 int q=other[p]; 22 if (!dfn[q]) { 23 tarjan(q); 24 low[x]=min(low[x],low[q]); 25 } else if (vis[q]) low[x]=min(low[x],dfn[q]); 26 } 27 if (dfn[x]==low[x]) { 28 int sum=0; 29 cnt++; 30 int now=stack[top--]; 31 cir[now]=1; 32 vis[now]=0; 33 huan[now]=cnt; 34 sum++; 35 while (now!=x) { 36 now=stack[top--]; 37 cir[now]=1; 38 vis[now]=0; 39 huan[now]=cnt; 40 sum++; 41 } 42 summ[cnt]=sum; 43 } 44 } 45 46 int dfs(int x) { 47 if (f[x]) return f[x]; 48 if (next[x]==x) { 49 f[x]=1; 50 return f[x]; 51 } 52 if (cir[x]) { 53 f[x]=summ[huan[x]]; 54 return f[x]; 55 } 56 if (cir[next[x]]) { 57 f[x]=summ[huan[next[x]]]+1; 58 return f[x]; 59 } 60 f[x]=dfs(next[x])+1; 61 return f[x]; 62 } 63 64 int main() { 65 scanf("%d",&n); 66 for (int i=1; i<=n; i++) { 67 int x; 68 scanf("%d",&x); 69 next[i]=x; 70 if (x!=i) add(i,x);//其实这里没有必要建边,用next数组即可。 71 } 72 for (int i=1; i<=n; i++) 73 if (!dfn[i]) tarjan(i);//tarjan缩点 74 for (int i=1; i<=n; i++) if (summ[huan[i]]==1) cir[i]=0; 75 //for (int i=1; i<=n; i++) printf("%d\n",cir[i]); 76 for (int i=1; i<=n; i++) printf("%d\n",dfs(i));//记忆化搜索 77 return 0; 78 }
以上是关于[USACO08DEC] Trick or Treat on the Farm的主要内容,如果未能解决你的问题,请参考以下文章
题解[USACO08DEC-Gold] Trick or Treat on the Farm
[USACO08DEC]Trick or Treat on the Farm
[USACO08DEC] Trick or Treat on the Farm
P2921 [USACO08DEC]Trick or Treat on the Farm G(Targan)
[USACO08DEC]在农场万圣节Trick or Treat on the Farm
P2921 [USACO08DEC]在农场万圣节Trick or Treat on the Farm(Tarjan+记忆化)