[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颗糖果. 农场不大,所以约翰要想尽法子让奶牛们得到快乐.他给每一个牛棚设置了一个“后继牛棚”.牛棚i的后继牛棚是Xi.他告诉奶牛们,她们到了一个牛棚之后,只要再往后继牛棚走去,就可以搜集到很多糖果.事实上这是一种有点欺骗意味的手段,来节约他的糖果.  第i只奶牛从牛棚i开始她的旅程.请你计算,每一只奶牛可以采集到多少糖果.

Input

第1行输入N,之后一行一个整数表示牛棚i的后继牛棚Xi,共N行.

Output

共N行,一行一个整数表示一只奶牛可以采集的糖果数量.

Sample Input

4        //有四个点
1       //1有一条边指向1
3      //2有一条边指向3
2     //3有一条边指向2
3

INPUT DETAILS:

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

Sample Output

1
2
2
3

缩点之后在DAG上递推

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
char buf[10000000], *ptr = buf - 1;
inline int readint(){
    int n = 0;
    char ch = *++ptr;
    while(ch < ‘0‘ || ch > ‘9‘) ch = *++ptr;
    while(ch <= ‘9‘ && ch >= ‘0‘){
        n = (n << 1) + (n << 3) + ch - ‘0‘;
        ch = *++ptr;
    }
    return n;
}
const int maxn = 200000 + 10;
struct Edge{
    int to, next;
    Edge(){}
    Edge(int _t, int _n): to(_t), next(_n){}
}e[maxn];
int fir[maxn] = {0}, cnt = 0;
inline void add(int u, int v){
    e[++cnt] = Edge(v, fir[u]); fir[u] = cnt;
}
int n;
int dfn[maxn] = {0}, low[maxn], idx = 0;
int belong[maxn], bcnt;
int sta[maxn], top = 0;
bool ins[maxn] = {false};
int f[maxn];
void tarjan(int u){
    dfn[u] = low[u] = ++idx;
    sta[++top] = u;
    ins[u] = true;
    for(int v, i = fir[u]; i; i = e[i].next){
        v = e[i].to;
        if(!dfn[v]){
            tarjan(v);
            low[u] = min(low[u], low[v]);
        }
        else if(ins[v]) low[u] = min(low[u], dfn[v]);
    }
    if(low[u] == dfn[u]){
        int now;
        bcnt++;
        f[bcnt] = 0;
        do{
            now = sta[top--];
            ins[now] = false;
            belong[now] = bcnt;
            f[bcnt]++;
        }while(now != u);
    }
}
int ind[maxn] = {0};
int q[maxn], h, t;
void tsort(){
    h = t = 0;
    for(int i = n + 1; i <= bcnt; i++)
        if(!ind[i]) q[t++] = i;
    int u, v;
    while(h != t){
        u = q[h++];
        for(int i = fir[u]; i; i = e[i].next){
            v = e[i].to;
            ind[v]--;
            if(!ind[v]) q[t++] = v;
        }
    }
    for(int i = t - 1; ~i; i--){
        for(int j = fir[q[i]]; j; j = e[j].next)
            f[q[i]] += f[e[j].to];
    }
}
int main(){
    fread(buf, sizeof(char), sizeof(buf), stdin);
    n = bcnt = readint();
    for(int x, i = 1; i <= n; i++){
        x = readint();
        if(x != i) add(i, x);
    }
    for(int i = 1; i <= n; i++)
        if(!dfn[i]) tarjan(i);
    for(int i = 1; i <= n; i++)
        for(int j = fir[i]; j; j = e[j].next)
            if(belong[i] != belong[e[j].to]){
                add(belong[i], belong[e[j].to]);
                ind[belong[e[j].to]]++;
            }
    tsort();
    for(int i = 1; i <= n; i++)
        printf("%d\n", f[belong[i]]);
    return 0;
}
时间: 2024-08-05 08:26:45

[BZOJ1589][Usaco2008 Dec]Trick or Treat on the Farm 采集糖果的相关文章

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

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

bzoj 1589: [Usaco2008 Dec]Trick or Treat on the Farm 采集糖果【tarjan+记忆化搜索】

对这个奇形怪状的图tarjan,然后重新连边把图变成DAG,然后记忆化搜索即可 #include<iostream> #include<cstdio> using namespace std; const int N=100005; int n,a[N],h[N],cnt,dfn[N],low[N],tot,s[N],top,bl[N],si[N],col,mp[N]; bool v[N]; struct qwe { int ne,to; }e[N]; int read() { i

[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颗糖果. 农场不大,所以约翰要想尽法子

洛谷 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】【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

[USACO08DEC] Trick or Treat on the Farm

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

[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 Trick or Treat on the Farm

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