### 题意翻译

#### 题目描述

FJ命令奶牛i应该从i号隔间开始收集糖果。如果一只奶牛回到某一个她已经去过的隔间，她就会停止收集糖果。

#### 输出格式

n行，第i行包含一个整数，表示第i只奶牛要前往的隔间数。

### 题目描述

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 large, FJ makes sure the cows extend their fun by specifying a traversal route the cows must follow. To implement this scheme for traveling back and forth through the barn, FJ has posted a 'next stall number' next_i (1 <= next_i <= N) on stall i that tells the cows which stall to visit next; the cows thus might travel the length of the barn many times in order to collect their candy.

FJ mandates that cow i should start collecting candy at stall i. A cow stops her candy collection if she arrives back at any stall she has already visited.

Calculate the number of unique stalls each cow visits before being forced to stop her candy collection.

POINTS: 100

### 输入格式

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

### 题解

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <algorithm>
#include <string.h>

using namespace std;

const int MAXN = 1e5 + 5;
int n, next[MAXN], vis[MAXN], ans[MAXN], p;

int main()
{
cin >> n;
for(int i = 1; i <= n; i++)
{
cin >> next[i];
}
for(int i = 1; i <= n; i++)
{
memset(vis, 0, sizeof(vis));
ans[i] = 1;
p = i;
vis[p] = 1;
while(vis[next[p]] == 0)
{
vis[next[p]] = 1;
p = next[p];
ans[i]++;
}
}
for(int i = 1; i <= n; i++)
{
cout << ans[i] << endl;
}

return 0;
}

染色的过程有两种可能：

1）染色的过程遇到了同种颜色的节点，例如下图中2-3-4-3。

2）染色的过程中遇到了不同颜色的节点，例如下图中的5-2和6-4。

1）所遇到的不同颜色的节点在环上，如4号节点。这种情况隔间数等于cnt+环长。

2）所遇到的不同颜色的节点不在环上，如2号节点。这种情况隔间数等于cnt+环长+从所遇到的节点到第一个进入环的节点的距离。

 1 #include <iostream>
2 #include <stdio.h>
3 #include <math.h>
4 #include <algorithm>
5 #include <string.h>
6
7 using namespace std;
8
9 const int MAXN = 1e5 + 5;
10 int n, next[MAXN], vis[MAXN], ans[MAXN], p;
11 int dfn[MAXN], cnt;
12 int looplen[MAXN]; // 环长
13 int stloop[MAXN]; // 路径中进入环的第一个节点的dfn值
14
15 int main()
16 {
17     cin >> n;
18     for(int i = 1; i <= n; i++)
19     {
20         cin >> next[i];
21     }
22
23     memset(vis, 0, sizeof(vis));
24     for(int i = 1; i <= n; i++)
25     {
26         cnt = 0;
27         p = i;
28         while(vis[p] == 0)
29         {
30             vis[p] = i;
31             dfn[p] = cnt;
32             p = next[p];
33             cnt++;
34         }
35         if(vis[p] == i)
36         { // 走到了自己染色的环
37             ans[i] = cnt;
38             looplen[i] = cnt - dfn[p];
39             stloop[i] = dfn[p];
40          }
41          else
42          { // 走到了其他点染色的路径
43              looplen[i] = looplen[vis[p]];
44              stloop[i] = cnt;
45              if(stloop[vis[p]] > dfn[p])
46             { // 遇到的点不在环上
47                  stloop[i] += stloop[vis[p]] - dfn[p];
48             }
49              ans[i] = stloop[i] + looplen[i];
50          }
51     }
52     for(int i = 1; i <= n; i++)
53     {
54         cout << ans[i] << endl;
55     }
56
57     return 0;
58 }

posted on 2019-08-24 21:50  zealsoft  阅读(...)  评论(...编辑  收藏