1. 程式人生 > >洛谷——P2921 [USACO08DEC]在農場萬聖節Trick or Treat on the Farm

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

badge radius clas 通過 name printf 要去 ret print

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

題意翻譯

題目描述

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

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

FJ命令奶牛i應該從i號隔間開始收集糖果。如果一只奶牛回到某一個她已經去過的隔間,她就會停止收集糖果。

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

輸入格式

第1行 整數n。

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

輸出格式

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

樣例解釋

有4個隔間

隔間1要求牛到隔間1

隔間2要求牛到隔間3

隔間3要求牛到隔間2

隔間4要求牛到隔間3

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

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

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

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

翻譯提供者:吃葡萄吐糖

題目描述

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

每年萬聖節,威斯康星的奶牛們都要打扮一番,出門在農場的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.

tarjan縮點+記憶化搜索

#include<bits/stdc++.h>

#define N 1500000
using namespace std;

int next[N],n,p[N];

int dfn[N],low[N],item,cnt,all[N],belong[N];
stack<int>S;
bool vis[N];
void tarjan(int u){
    dfn[u]=low[u]=++item;vis[u]=1;S.push(u);
    int v=next[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(low[u]==dfn[u]){
        int v;++cnt;
        do{
            v=S.top();S.pop();
            belong[v]=cnt;++all[cnt];vis[v]=0;
        }while(v!=u);
    }
}

int dfs(int u){
    if(p[u]) return p[u];
    if(all[belong[u]]>1||next[u]==u) return all[belong[u]];
    return p[u]=dfs(next[u])+1;
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&next[i]);
    for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
    for(int i=1;i<=n;i++){
        if(all[belong[i]]==1){
            printf("%d\n",dfs(i));
        } else printf("%d\n",all[belong[i]]);
    }
    return 0;
}

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