[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
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
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; }