传送门

题目

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

分析

首先我们先进行Tarjan缩点,将每点权值赋为环中点数,意为走入这个环可获得的糖果数。因为只有一条出边,所以之后我们便进行dfs,从每一个点出发所获糖果数即为它自身权值+由它到达的点出发所能获得的糖果数。

代码

#include<iostream>

#include<cstdio>

#include<cstring>

#include<string>

#include<algorithm>

#include<cctype>

#include<cmath>

#include<cstdlib>

#include<ctime>

#include<queue>

#include<vector>

#include<set>

#include<map>

#include<stack>

using namespace std;

int vis[110000],size[110000],nxt[110000],ist[110000],dfn[110000],low[110000];

int sum,cnt,belong[110000],nxt2[110000],all[110000];

stack<int>a;

inline void read(int &x){

      int f=1;x=0;

      char s=getchar();

      while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}

      while(s>='0'&&s<='9'){x=x*10+(s-'0');s=getchar();}

      x*=f;

}

inline void tarjan(int x){

      dfn[x]=low[x]=++cnt;

      a.push(x);

      ist[x]=1;

      if(!dfn[nxt[x]]){

          tarjan(nxt[x]);

          low[x]=min(low[x],low[nxt[x]]);

      }else if(ist[nxt[x]]){

          low[x]=min(low[x],dfn[nxt[x]]);

      }

      if(dfn[x]==low[x]){

          sum++;

          while(1){

              int u=a.top();

              a.pop();

              ist[u]=0;

              belong[u]=sum;

              all[sum]++;

              if(u==x)break;

          }

      }

}

inline void go(int x){

      if(size[x])return;

      size[x]=all[x];

      vis[x]=1;

      if(!nxt2[x])return;

      go(nxt2[x]);

      size[x]+=size[nxt2[x]];

}

int main(){

      int n,m,i,j,k;

      read(n);

      for(i=1;i<=n;i++)read(nxt[i]);

      for(i=1;i<=n;i++)

         if(!dfn[i])tarjan(i);

      for(i=1;i<=n;i++)

         if(belong[i]!=belong[nxt[i]])nxt2[belong[i]]=belong[nxt[i]];

      for(i=1;i<=sum;i++)

         if(!vis[i])

           go(i);

      for(i=1;i<=n;i++)printf("%d\n",size[belong[i]]);

      return 0;

}