P2921 [USACO08DEC]在農場萬聖節Trick or Treat on the Farm
分析:
這棵樹上有且僅有一個環
兩種情況:
1.討論一個點在環上,如果在則答案與它指向點相同,
2.不在就等於它指向點答案+1,具體就直接大力dfs,
如何求環長度:
終點深度-起點深度=終點起點距離
#include<cstdio> #include<string> #include<cstring> using namespace std; const int maxn=100005; int n; int cnt=1; int a[maxn]; int h[maxn]; int ans[maxn]; int read() //快讀 { int x=0,f=1;char c=getchar(); while(!isdigit(c)){if(c=='-')f=-1;c=getchar();} while(isdigit(c)){x=x*10+c-'0';c=getchar();} return x*f; } void dfs(int i,int deep) { h[i]=deep; //該點深度 if(ans[a[i]]) ans[i]=ans[a[i]]+1; //若指向點有答案,而自己無答案,則自己不再環上。要+1 else if(h[a[i]]) //若形成環 { ans[i]=(h[i]-h[a[i]]+1); //重新整理該點答案 int k=a[i]; while(i!=k) //重新整理環內所有答案 ,直到回到原點 { ans[k]=ans[i]; k=a[k]; } } else { dfs(a[i],deep+1); if(!ans[i]) ans[i]=ans[a[i]]+1; //自身肯定不再環上,所以+1 } } void solve() { for (int i=1;i<=n;i++) { if(!ans[i]) dfs(i,0); //若此點未有涉及(無答案),就dfs } for (int i=1;i<=n;i++) printf("%d\n",ans[i]); } void work() { n=read(); for(int i=1;i<=n;i++) { a[i]=read(); } solve(); } int main() { work(); return 0; }