【洛谷P2921】[USACO08DEC]在农场万圣节 在农场万圣节Trick or Treat on the Farm
题解:
首先,将原图缩点,变为DAG,
然后在DAG上记忆化搜索即可
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 using namespace std; 5 #define N 100010 6 #define reset(a) memset(a,0,sizeof(a)) 7 int n,next[N],belong[N],num; 8 int Next[N],f[N],size[N]; 9 int dfn[N],low[N],cnt; 10 int stack[N],top; 11 bool ins[N]; 12 void dfs(int t){ 13 dfn[t]=low[t]=++cnt; 14 stack[++top]=t; 15 ins[t]=1; 16 int v=next[t]; 17 if(!dfn[v]){ 18 dfs(v); 19 low[t]=min(low[t],low[v]); 20 } 21 else if(ins[v]) 22 low[t]=min(low[t],dfn[v]); 23 if(low[t]==dfn[t]){ 24 num++; 25 size[num]++; 26 while(stack[top]!=t){ 27 size[num]++; 28 int u=stack[top]; 29 belong[u]=num; 30 ins[u]=0; 31 top--; 32 } 33 top--; 34 ins[t]=0; 35 belong[t]=num; 36 } 37 } 38 int Dfs(int t){ 39 if(f[t]) return f[t]; 40 if(!Next[t]) return f[t]=size[t]; 41 return f[t]=size[t]+Dfs(Next[t]); 42 } 43 int main() 44 { 45 scanf("%d",&n); 46 for(int i=1;i<=n;i++) 47 scanf("%d",&next[i]); 48 for(int i=1;i<=n;i++) 49 if(!dfn[i]) dfs(i); 50 for(int i=1;i<=n;i++) 51 if(belong[i]!=belong[next[i]]) 52 Next[belong[i]]=belong[next[i]]; 53 for(int i=1;i<=n;i++){ 54 if(!f[belong[i]]) 55 Dfs(belong[i]); 56 printf("%d ",f[belong[i]]); 57 } 58 return 0; 59 }