1. 程式人生 > >信息傳遞 NOIP2015 day1 T2

信息傳遞 NOIP2015 day1 T2

ems mes noi ostream struct pop div empty 只知道

題文:

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

輸入共2行。
第1行包含1個正整數n表示n個人。
第2行包含n個用空格隔開的正整數T1,T2,……,Tn其中第i個整數Ti示編號為i 的同學的信息傳遞對象是編號為Ti的同學,Ti≤n且Ti≠i
數據保證遊戲一定會結束。

輸出共 1行,包含 1個整數,表示遊戲一共可以進行多少輪。

這題目看上去是在找一個有向圖的最小環,因為每個點只有一個出度,所以圖中不可能出現強連通分量中套著

強連通分量的情況,所以我們只要跑遍tarjian,統計每個分量的size就可以了;

但是n平方的算法為啥沒T掉,求解;

AC代碼:

#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<cstring>
#include<stack>
#include<algorithm> 
using
namespace std; const int MAXN=2000020; int n,num=0,num1=0; int dfn[MAXN],low[MAXN]; bool in[MAXN]; int ans=1<<30; struct edge{ int first; int next; int quan; int to; }a[MAXN]; void addedge(int from,int to){ a[++num].to=to; a[num].next=a[from].first; a[num].quan=1; a[from
].first=num; } stack<int> q; void tarjian(int now){ dfn[now]=low[now]=num1++; in[now]=1; q.push(now); for(int i=a[now].first;i;i=a[i].next){ int to=a[i].to; if(!dfn[to]){ tarjian(to); low[now]=min(low[now],low[to]); } else if(in[to]){ low[now]=min(low[now],dfn[to]); } } if(low[now]==dfn[now]){ int u=-1,size=0; while(u!=now){ u=q.top(); q.pop(); in[u]=0; size++; } if(size!=1) ans=min(ans,size); } } int main() { memset(in,0,sizeof(in)); while(!q.empty()) q.pop(); cin>>n; for(int i=1;i<=n;i++){ int x; scanf("%d",&x); addedge(i,x); } for(int i=1;i<=n;i++){ if(!dfn[i]){ tarjian(i); } } printf("%d",ans); }

信息傳遞 NOIP2015 day1 T2