noip201506 Message 信息傳遞

試題描述:ios

有 n 個同窗(編號爲 1 到 n )正在玩一個信息傳遞的遊戲。在遊戲裏每人都有一個固定的信息傳遞對象,其中,編號爲 i 的同窗的信息傳遞對象是編號爲 T_i 的同窗。遊戲開始時,每人都只知道本身的生日。以後每一輪中,全部人會同時將本身當前所知的生日信息告訴各自的信息傳遞對象(注意:可能有人能夠從若干人那裏獲取信息, 可是每人只會把信息告訴一我的,即本身的信息傳遞對象)。當有人從別人口中得知自 己的生日時,遊戲結束。請問該遊戲一共能夠進行幾輪?git

輸入:ide

共2行,第1行包含1個正整數 n ,表示 n 我的。
第2行包含 n 個用空格隔開的正整數T_1,T_2,...,T_n ,其中第 i 個整數 T_i 表示編號爲 i 的同窗的信息傳遞對象是編號爲 T_i 的同窗, T_i <= n 且 T_i 不等於 i 。
數據保證遊戲必定會結束。spa

輸出:code

共1行,包含1個整數,表示遊戲一共能夠進行多少輪。對象

輸入示例:blog

5
2 4 2 3 1
遊戲

輸出示例:get

3it

數據範圍:

n<=200000

--------------------------------------------分隔線--------------------------------------------------------

這題看了題就知道其實咱們所要乾的一件事就是找最小環……(其實我考試的時候也知道是要最小環,可不知道怎麼找啊……因而乎寫了一個根本錯的東西但不知道怎麼回事還蒙了30分……學了一年C++,就差這麼一道題的70,個人省一啊……)

上面的廢話選擇性忽略好了……下面來講這道題的重點……

找最小環的話果斷要用到強連通份量。

強連通份量:對於一個有向圖的頂點的子集S,若是在S內任取兩個頂點u和v,都能找到一條從u到v的路徑,那麼就稱S是強連通的。若是在強連通的頂點集合S中加入其餘任意頂點集合後,它都再也不是強連通的,那麼就稱S是原圖的一個強連通份量(SCC :Strongly Connected Component)

強連通份量的分解能夠用兩次簡單的dfs來實現。

第一次dfs的時候,選取任意頂點做爲起點,遍歷全部未訪問過的頂點,在回溯前給定點標號。對剩餘未訪問過的頂點不斷重複上述過程。

完成標號後越接近圖的尾部,定點的標號越小。

第二次dfs時先將全部的邊反向,而後以標號最大的頂點爲起點進行dfs,這樣能夠把圖的拓撲序儲存。

代碼以下:

 1 #include<iostream>
 2 #include<cctype>
 3 using namespace std;
 4 const int MAXN=200000+10;
 5 void read(int &x){
 6     x=0;int f=1;char ch=getchar();
 7     for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
 8     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';
 9     x*=f;
10 }
11 //----------------------
12 int v[MAXN],first[MAXN],next[MAXN],e;
13 void AddEdge(int a,int b){
14     v[++e]=b;
15     next[e]=first[a];
16     first[a]=e;
17 }
18 
19 int vr[MAXN],firstr[MAXN],nextr[MAXN],er;
20 void AddEdger(int a,int b){
21     vr[++er]=b;
22     nextr[er]=firstr[a];
23     firstr[a]=er;
24 }
25 //----------------------
26 int n,tot,vs[MAXN],topo[MAXN];
27 bool vis[MAXN];
28 void dfs(int x){
29     vis[x]=1;
30     for(int i=first[x];i;i=next[i])
31         if(!vis[v[i]])dfs(v[i]);
32     vs[++tot]=x;
33 }
34 
35 void dfsr(int x,int k){
36     vis[x]=1;
37     topo[x]=k;
38     for(int i=firstr[x];i;i=nextr[i])
39         if(!vis[vr[i]])dfsr(vr[i],k);
40 }
41 //---------------------------
42 int cnt[MAXN];
43 int main(){
44     read(n);
45     for(int i=1;i<=n;i++){
46         int tmp;
47         read(tmp);
48         AddEdge(i,tmp);
49         AddEdger(tmp,i);
50     }
51 
52     memset(vis,0,sizeof(vis));
53     for(int i=1;i<=n;i++)
54         if(!vis[i])dfs(i);
55 
56     int k=1;
57     memset(vis,0,sizeof(vis));
58     for(int i=n;i>=1;i--)
59         if(!vis[vs[i]])dfsr(vs[i],k++);
60 
61     for(int i=1;i<=n;i++)cnt[topo[i]]++;
62     int ans=-1u>>1;
63     for(int i=1;i<=topo[vs[1]];i++){
64         if(cnt[i]!=1)ans=min(ans,cnt[i]);
65     }
66     printf("%d\n",ans);
67 }
View Code
相關文章
相關標籤/搜索