[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
", f[belong[i]]);
    return 0;
}
原文地址:https://www.cnblogs.com/ruoruoruo/p/7553473.html