缩成DAG
f(i)表示以i为起点的最长路
#include<cstdio> #include<cstring> #include<algorithm> #include<vector> using namespace std; #define N 100001 int n,To[N],mem[N]; vector<int>vs; int v[N],first[N],next[N],en; void AddEdge(int U,int V) { v[++en]=V; next[en]=first[U]; first[U]=en; } int v2[N],firs2[N],nex2[N],e2; void AddEdg2(int U,int V) { v2[++e2]=V; nex2[e2]=firs2[U]; firs2[U]=e2; } int w[N],cmp[N],tot; bool vis[N]; void dfs(int U) { vis[U]=1; for(int i=first[U];i;i=next[i]) if(!vis[v[i]]) dfs(v[i]); vs.push_back(U); } void df2(int U) { cmp[U]=tot; ++w[tot]; for(int i=firs2[U];i;i=nex2[i]) if(!cmp[v2[i]]) df2(v2[i]); } void scc() { for(int i=1;i<=n;++i) if(!vis[i]) dfs(i); vector<int>::iterator it=vs.end(); --it; while(1) { if(!cmp[*it]) { ++tot; df2(*it); } if(it==vs.begin()) break; --it; } } int f(int U) { if(mem[U]) return mem[U]; mem[U]=w[U]; for(int i=first[U];i;i=next[i]) mem[U]=max(mem[U],f(v[i])+w[U]); return mem[U]; } int main() { scanf("%d",&n); for(int i=1;i<=n;++i) { scanf("%d",&To[i]); AddEdge(i,To[i]); AddEdg2(To[i],i); } scc(); memset(first,0,sizeof(first)); memset(next,0,sizeof(next)); memset(v,0,sizeof(v)); en=0; for(int i=1;i<=n;++i) if(cmp[i]!=cmp[To[i]]) AddEdge(cmp[i],cmp[To[i]]); for(int i=1;i<=n;++i) printf("%d ",f(cmp[i])); return 0; }