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颗糖果. 农场不大,所以约翰要想尽法子让奶牛们得到快乐.他给每一个牛棚设置了一个“后继牛棚”.牛棚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
HINT
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.
Source
tarjan缩环然后记忆化搜一下……(写完才反应过来一个点只有一个后继,根本不用数组模拟链表,开个数组记录一下就好了)
#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 ",search(belong[i])); return 0; }