洛谷 2921 [USACO08DEC]在农场万圣节Trick or Treat on the Farm

【题解】

  就是基环外向树森林找环,然后从环向外统计size就可以了。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<vector>
 5 #define LL long long
 6 #define rg register
 7 #define N 200010
 8 using namespace std;
 9 int n,color,top,to[N],siz[N],st[N],pos[N];
10 bool v[N],c[N];
11 vector<int>from[N];
12 inline int read(){
13     int k=0,f=1; char c=getchar();
14     while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
15     while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
16     return k*f;
17 }
18 void calc(int x){
19     v[x]=1;
20     for(rg int i=0;i<from[x].size();i++)if(!siz[from[x][i]]){
21         siz[from[x][i]]=siz[x]+1; calc(from[x][i]);
22     }
23 }
24 void dfs(int x){
25     v[x]=1; st[pos[x]=++top]=x;
26     if(pos[to[x]]){
27         int Size=top-pos[to[x]]+1;
28         for(rg int i=pos[to[x]];i<=top;i++) siz[st[i]]=Size,c[st[i]]=1;
29         for(rg int i=pos[to[x]];i<=top;i++) calc(st[i]);
30 //        printf("%d %d
",to[x],x);
31         top=pos[to[x]]--;
32     }
33     else dfs(to[x]);
34     top--; pos[x]=0;
35 }
36 int main(){
37     n=read();
38     for(rg int i=1;i<=n;i++) to[i]=read(),from[to[i]].push_back(i); 
39 //    for(rg int i=1;i<=n;i++){
40 //        for(rg int j=0;j<from[i].size();j++) printf("%d ",from[i][j]); puts("");
41 //    }
42     for(rg int i=1;i<=n;i++) if(!v[i]) dfs(i);
43     for(rg int i=1;i<=n;i++) printf("%d
",siz[i]);
44     return 0;
45 }
原文地址:https://www.cnblogs.com/DriverLao/p/9795788.html