先来大概说一下今天的考试,今天是集训以来第一次NOI赛制的训练,由于四道有两道原题,所以也是我集训以来考的最好的一次,如果不算因为‘\r’引起的那一百分的失分的话,进前五应该是没有问题的,但是毕竟是错了,这是一个值得反思的地方,WIndows的换行不只有'\n',还有'\r',所以以后如果我想要输入一个字符的话,尽量还是用scanf,还有在现阶段快读并不是那么必要(lin大佬本来可以满分的,因为这个扣了200分),在非必须的情况下尽量不要用(当然时间卡的特别紧输入又多的毒瘤题另当别论)
今天的题不像往常多,只有四道,往常我的博客很少写上所有的题,但是今天都写上吧,就当是做个纪念.
在这次考试之中这道题也算是一道比较简单的题了,从题意之中我们可以读出每个点只有一个出边,于是我们不用去考虑环套环的情况,由于消息穿一圈又回到自己一定是个环,于是考虑用tarjan求出图里面的强连通分量的大小,在特判掉大小为一的连通分量的前提下求出最小的连通分量的大小就行了(写这么少不是我想水,而是这道题真的没什么说的QAQ);
1 #include<cstdio> 2 #include<stack> 3 #include<cstring> 4 #include<algorithm> 5 const int N=4e5+10; 6 using namespace std; 7 struct Node{ 8 int next,to; 9 }edge[N]; 10 int Head[N],tot; 11 void Add(int x,int y){ 12 edge[++tot].to=y; 13 edge[tot].next=Head[x]; 14 Head[x]=tot; 15 } 16 stack<int>sta; 17 int dfn[N],low[N],dfn_cnt,scc_cnt,siz[N],belong[N]; 18 void tarjan(int u){ 19 dfn[u]=low[u]=++dfn_cnt; 20 sta.push(u); 21 for(int i=Head[u];i;i=edge[i].next){ 22 int v=edge[i].to; 23 if(!dfn[v]){ 24 tarjan(v); 25 low[u]=min(low[u],low[v]); 26 } 27 else if(!belong[v]) low[u]=min(low[u],dfn[v]); 28 } 29 if(dfn[u]==low[u]){ 30 scc_cnt++; 31 int t; 32 do{ 33 t=sta.top();sta.pop(); 34 belong[t]=scc_cnt; 35 siz[scc_cnt]++; 36 }while(t!=u); 37 } 38 } 39 int main(){ 40 //freopen("a.in","r",stdin); 41 //freopen("a.out","w",stdout); 42 int n; 43 scanf("%d",&n); 44 for(int i=1;i<=n;++i){ 45 int x; 46 scanf("%d",&x); 47 Add(i,x); 48 } 49 for(int i=1;i<=n;++i){ 50 if(!dfn[i]) tarjan(i); 51 } 52 int ans=0x3f3f3f3f; 53 for(int i=1;i<=scc_cnt;++i){ 54 if(siz[i]!=1) ans=min(ans,siz[i]); 55 } 56 printf("%d\n",ans); 57 return 0; 58 }