每年万圣节,威斯康星的奶牛们都要打扮一番,出门在农场的N(1≤N≤100000)个牛棚里转悠,来采集糖果.她们每走到一个未曾经过的牛棚,就会采集这个棚里的1颗糖果. 农场不大,所以约翰要想尽法子让奶牛们得到快乐.他给每一个牛棚设置了一个“后继牛棚”.牛棚i的后继牛棚是Xi.他告诉奶牛们,她们到了一个牛棚之后,只要再往后继牛棚走去,就可以搜集到很多糖果.事实上这是一种有点欺骗意味的手段,来节约他的糖果. 第i只奶牛从牛棚i开始她的旅程.请你计算,每一只奶牛可以采集到多少糖果.
标签:
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.
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<vector> #define MAX 100005 using namespace std; int top,n,x,tot,sum,cnt,tot0; int stack[MAX],inset[MAX],num[MAX],next[MAX],list[MAX],next0[MAX],list0[MAX],dfn[MAX],low[MAX],head[MAX],head0[MAX],ans[MAX],belong[MAX]; void insert(int x,int y) { next[++tot]=head[x]; head[x]=tot; list[tot]=y; } void insert0(int x,int y) { next0[++tot0]=head0[x]; head0[x]=tot0; list0[tot0]=y; } void dfs(int x) { dfn[x]=low[x]=++sum; stack[++top]=x; inset[x]=1; for (int i=head[x];i;i=next[i]) { if (!dfn[list[i]]) { dfs(list[i]); low[x]=min(low[x],low[list[i]]); } if (inset[list[i]]) low[x]=min(low[x],dfn[list[i]]); } int y=-1; if (dfn[x]==low[x]) { cnt++; while (y!=x) { y=stack[top--]; inset[y]=0; belong[y]=cnt; num[cnt]++; } } } void tarjan() { for (int i=1;i<=n;i++) if (!dfn[i]) dfs(i); } void rebuild() { for (int i=1;i<=n;i++) for (int j=head[i];j;j=next[j]) if (belong[i]!=belong[list[i]]) insert0(belong[i],belong[list[j]]); } int search(int x) { if (ans[x]!=-1) return ans[x]; ans[x]=num[x]; ans[x]+=search(list0[head0[x]]); return ans[x]; } int main() { scanf("%d",&n); for (int i=1;i<=n;i++) { scanf("%d",&x); insert(i,x); } tarjan(); rebuild(); memset(ans,-1,sizeof(ans)); for (int i=1;i<=n;i++) printf("%d\n",search(belong[i])); return 0; }
[Usaco2008 Dec][BZOJ1589] Trick or Treat on the Farm 采集糖果
标签:
原文地址:http://www.cnblogs.com/ws-fqk/p/4663302.html