这道题是一个裸的强连通分量的题(最短路也可以解这道题)
把每个同学看成一个点,信息的传递就是在他们之间连有向边,游戏最小轮数就是求最小环。
用强连通分量做,有一个坑点,就是当某个联通分量的大小为1的时候,不能把它算作答案(我因为这个点被坑了,WA到怀疑人生)
我们不用记录强连通的并查集,我们只记录所有分量的大小即可。剩下的就是tarjan的事情了。
附上AC代码
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> #include<iostream> using namespace std; template<class T> inline void read(T &_a){ bool f=0;int _ch=getchar();_a=0; while(_ch<'0' || _ch>'9'){if(_ch=='-')f=1;_ch=getchar();} while(_ch>='0' && _ch<='9'){_a=(_a<<1)+(_a<<3)+_ch-'0';_ch=getchar();} if(f)_a=-_a; } const int maxn=200001; int n,egcnt,head[maxn],dfn[maxn],low[maxn],idx,stk[maxn],stkcnt,sz[maxn],becnt; bool ins[maxn]; struct edge { int to,next; }w[maxn]; void tarjan(int u) { dfn[u]=low[u]=++idx; stk[++stkcnt]=u; ins[u]=true; for (register int i=head[u];i;i=w[i].next) { if(!dfn[w[i].to]) { tarjan(w[i].to); low[u]=min(low[u],low[w[i].to]); } else if(ins[w[i].to]) low[u]=min(low[u],dfn[w[i].to]); } if(dfn[u]==low[u]) { ++becnt; while(stk[stkcnt]!=u) { ins[stk[stkcnt]]=false; --stkcnt; ++sz[becnt]; } ins[u]=false; --stkcnt; ++sz[becnt]; } } inline void addedge(int from,int to) { w[++egcnt].to=to; w[egcnt].next=head[from]; head[from]=egcnt; } int main() { read(n); for (register int i=1,a;i<=n;++i) read(a),addedge(i,a); for (register int i=1;i<=n;++i) if(!dfn[i]) tarjan(i); int ans=0x7fffffff; for (register int i=1;i<=becnt;++i) if(sz[i]!=1) ans=min(ans,sz[i]); printf("%d",ans); return 0; }