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

題意翻譯

題目描述

每一年,在威斯康星州,奶牛們都會穿上衣服,收集農夫約翰在N(1<=N<=100,000)個牛棚隔間中留下的糖果,以此來慶祝美國秋天的萬聖節。c++

因爲牛棚不太大,FJ經過指定奶牛必須遵循的穿越路線來確保奶牛的樂趣。爲了實現這個讓奶牛在牛棚裏來回穿梭的方案,FJ在第i號隔間上張貼了一個「下一個隔間」Next_i(1<=Next_i<=N),告訴奶牛要去的下一個隔間;這樣,爲了收集它們的糖果,奶牛就會在牛棚裏來回穿梭了。spa

FJ命令奶牛i應該從i號隔間開始收集糖果。若是一隻奶牛回到某一個她已經去過的隔間,她就會中止收集糖果。翻譯

在被迫中止收集糖果以前,計算一下每頭奶牛要前往的隔間數(包含起點)。code

輸入格式

第1行 整數n。blog

第2行到n+1行 每行包含一個整數 next_i 。it

輸出格式

n行,第i行包含一個整數,表示第i只奶牛要前往的隔間數。io

樣例解釋

有4個隔間class

隔間1要求牛到隔間1搜索

隔間2要求牛到隔間3next

隔間3要求牛到隔間2

隔間4要求牛到隔間3

牛1,從1號隔間出發,總共訪問1個隔間;

牛2,從2號隔間出發,而後到三號隔間,而後到2號隔間,終止,總共訪問2個隔間;

牛3,從3號隔間出發,而後到2號隔間,而後到3號隔間,終止,總共訪問2個隔間;

牛4,從4號隔間出發,而後到3號隔間,而後到2號隔間,而後到3號隔間,終止,總共訪問3個隔間。

輸入輸出格式

輸入格式:

 

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

 

/*
    用tarjan找環,而後縮點記錄環的大小,若點在一個環中ans即爲環的大小
    若不在環中,即爲到環的最短距離+環的大小
    記憶化搜索便可
*/
#include <bits/stdc++.h>

using namespace std;

const int maxn = 100005;

int dfn[maxn],low[maxn],nex[maxn],scc_cnt,scc_amount;
int stac[maxn],vis[maxn],top,scc[maxn],n,num[maxn],ans[maxn];


void tarjan(int u){
    dfn[u] = low[u] = ++scc_cnt;
    vis[u] = 1;stac[++top] = u;
        int v = nex[u];
        if(!dfn[v]){
            tarjan(v);
            low[u] = min(low[u],low[v]);
        }else if(vis[v]){
            low[u] = min(low[u],dfn[v]);
        }

     if(dfn[u] == low[u]){
        scc_amount++;
        while(stac[top] != u){
            int x=stac[top--];
            vis[x]=0;
            scc[x]=scc_amount;
            num[scc_amount]++;
        }
        int x=stac[top--];
        vis[x]=0;
        scc[x]=scc_amount;
        num[scc_amount]++;
    }
}

int dfs(int x){
    if(ans[x] > 1 || nex[x] == x) return ans[x];
    return ans[x] + dfs(nex[x]);
}

int main(){
    scanf("%d",&n);
    for(int i = 1;i <= n;i++) scanf("%d",&nex[i]);
    for(int i = 1;i <= n;i++){
        if(!dfn[i]) tarjan(i);
    }
    for(int i = 1;i <= n;i++) ans[i] = num[scc[i]];
    for(int i = 1;i <= n;i++){
        if(ans[i] == 1 && nex[i] != i) ans[i] = dfs(i);
    }
    for(int i = 1;i <= n;i++)
        printf("%d\n",ans[i]);
    return 0;
}
相關文章
相關標籤/搜索