//求圖中環的個數<br />//由於圖中每個點的出度只有1,所以不存在一個點處於兩個環的交點<br />//因此,求環的個數時每個只需要考慮一次便可得出結果<br />//由於資料規模龐大,寫成遞迴形式容易暴棧<br />//在讀邊的過程中先對自環進行預先處理,之後對每個點進行不同的染色,對它的下一個點也染同樣的顏色<br />//這樣染下去如果發現下一個要染的點和正在染的顏色相同,則說明存在一個環<br />//換染色起點的同時也需要更換新的染色,才能保證對環的判斷正確<br />#include<iostream><br />#include<cstring><br />using namespace std;<br />int next[1000001];//指向下一結點的指標<br />int vis[1000001];//對每個結點進行不同的標記<br />int ans,n,ringID,p;<br />void search()<br />{<br />for(int i = 1;i <= n;++i)<br />{<br />if(vis[i] > 0)continue;<br />p = i;<br />++ringID;//對每一種環進行一種不同的標記,新的起點必須更換新的染色<br />while(vis[p] == 0)//當前結點未被染色<br />{<br />vis[p] = ringID;//染色<br />p = next[p];//指向下一個點<br />if(vis[p] == ringID)//下一個點的顏色和當前染色相同,則說明存在一個環<br />++ans;<br />}<br />}<br />}<br />int main()<br />{<br />//freopen("in.txt","r",stdin);<br />while(scanf("%d",&n) != EOF)<br />{<br />ans = 0;<br />ringID = 1;<br />memset(vis,0,sizeof(vis));<br />for(int i = 1;i <= n;++i)<br />{<br />scanf("%d",&next[i]);<br />if(next[i] == i)<br />{<br />vis[i] = ringID++;//先對自環進行預先處理<br />ans++;<br />}<br />}<br />search();<br />printf("%d/n",ans);<br />}<br />return 0;<br />}