[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.

输入输出样例

输入样例#1:

4
1
3
2
3

输出样例#1:

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 }
时间: 2024-12-22 19:59:55

[USACO08DEC] Trick or Treat on the Farm的相关文章

P2921 [USACO08DEC]Trick or Treat on the Farm G(Targan)

https://www.luogu.com.cn/problem/P2921 #include<bits/stdc++.h> using namespace std; const int Maxn=100005; int nxt[Maxn]; int ans[Maxn]; int head[Maxn],cnt; struct road{ int to,next; }e[Maxn*2]; void add(int a,int b){ cnt++; e[cnt].to=b; e[cnt].next

洛谷 P2921 [USACO08DEC]在农场万圣节Trick or Treat on the Farm

P2921 [USACO08DEC]在农场万圣节Trick or Treat on the Farm 题目描述 Every year in Wisconsin the cows celebrate the USA autumn holiday of Halloween by dressing up in costumes and collecting candy that Farmer John leaves in the N (1 <= N <= 100,000) stalls conven

P2921 [USACO08DEC]在农场万圣节Trick or Treat on the Farm(Tarjan+记忆化)

P2921 [USACO08DEC]在农场万圣节Trick or Treat on the Farm 题意翻译 题目描述 每年,在威斯康星州,奶牛们都会穿上衣服,收集农夫约翰在N(1<=N<=100,000)个牛棚隔间中留下的糖果,以此来庆祝美国秋天的万圣节. 由于牛棚不太大,FJ通过指定奶牛必须遵循的穿越路线来确保奶牛的乐趣.为了实现这个让奶牛在牛棚里来回穿梭的方案,FJ在第i号隔间上张贴了一个“下一个隔间”Next_i(1<=Next_i<=N),告诉奶牛要去的下一个隔间:这样

[BZOJ1589][Usaco2008 Dec]Trick or Treat on the Farm 采集糖果

1589: [Usaco2008 Dec]Trick or Treat on the Farm 采集糖果 Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 719  Solved: 408 [Submit][Status][Discuss] Description 每年万圣节,威斯康星的奶牛们都要打扮一番,出门在农场的N(1≤N≤100000)个牛棚里转悠,来采集糖果.她们每走到一个未曾经过的牛棚,就会采集这个棚里的1颗糖果. 农场不大,所以约翰要想尽

[Usaco2008 Dec][BZOJ1589] Trick or Treat on the Farm 采集糖果

1589: [Usaco2008 Dec]Trick or Treat on the Farm 采集糖果 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 438  Solved: 244[Submit][Status][Discuss] Description 每年万圣节,威斯康星的奶牛们都要打扮一番,出门在农场的N(1≤N≤100000)个牛棚里转悠,来采集糖果.她们每走到一个未曾经过的牛棚,就会采集这个棚里的1颗糖果. 农场不大,所以约翰要想尽法子

[USACO08DEC]在农场万圣节Trick or Treat on the Farm

题目描述 Every year in Wisconsin the cows celebrate the USA autumn holiday of Halloween by dressing up in costumes and collecting candy that Farmer John leaves in the N (1 <= N <= 100,000) stalls conveniently numbered 1..N. Because the barn is not so la

P2921 [USACO08DEC]在农场万圣节Trick or Treat on the Farm 记忆化搜索dfs

题目描述 每年,在威斯康星州,奶牛们都会穿上衣服,收集农夫约翰在N(1<=N<=100,000)个牛棚隔间中留下的糖果,以此来庆祝美国秋天的万圣节. 由于牛棚不太大,FJ通过指定奶牛必须遵循的穿越路线来确保奶牛的乐趣.为了实现这个让奶牛在牛棚里来回穿梭的方案,FJ在第i号隔间上张贴了一个“下一个隔间”Next_i(1<=Next_i<=N),告诉奶牛要去的下一个隔间:这样,为了收集它们的糖果,奶牛就会在牛棚里来回穿梭了. FJ命令奶牛i应该从i号隔间开始收集糖果.如果一只奶牛回到某

【BZOJ1589】【USACO 2008 Dec Gold】 1.Trick or Treat on the Farm 基环树裸DP、

没测样例一遍A这真是-- 题意:每个点都有且仅有一个出边(可以出现自环),然后这样一个点出发就会走过且一定走过某些点. 问每个点出发都会走过几个点. 首先这是基环树无疑. 然后就是裸DP了. 这个的关键就是找环,仅此. #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define N 101000 using namespace std; int n

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

Description 每年万圣节,威斯康星的奶牛们都要打扮一番,出门在农场的N(1≤N≤100000)个牛棚里转悠,来采集糖果.她们每走到一个未曾经过的牛棚,就会采集这个棚里的1颗糖果. 农场不大,所以约翰要想尽法子让奶牛们得到快乐.他给每一个牛棚设置了一个"后继牛棚".牛棚i的后继牛棚是Xi.他告诉奶牛们,她们到了一个牛棚之后,只要再往后继牛棚走去,就可以搜集到很多糖果.事实上这是一种有点欺骗意味的手段,来节约他的糖果.  第i只奶牛从牛棚i开始她的旅程.请你计算,每一只奶牛可以采