这道题是一个裸的强连通分量的题(最短路也可以解这道题)
把每个同学看成一个点,信息的传递就是在他们之间连有向边,游戏最小轮数就是求最小环。
用强连通分量做,有一个坑点,就是当某个联通分量的大小为1的时候,不能把它算作答案(我因为这个点被坑了,WA到怀疑人生)
我们不用记录强连通的并查集,我们只记录所有分量的大小即可。剩下的就是tarjan的事情了。
附上AC代码
#include#include #include #include #include #include using namespace std;template 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;}