额,好水啊,有人说用tarjan但我觉得用tarjan都多余了 ,直接维护一个标记dfn:0表示没有进栈 1表示在栈中 2表示已经出栈,然后每一次dfs的时候发现如果回到了祖先就说明出现了环,找一个最小环就好了
可是我后来试了一下只有标记在栈中没有标记出栈 居然过了9组,数据有点水啊
#include<cstdio>
#include<cstring>
#include<iostream>
#define maxn 200020
using namespace std;
int n,head[maxn],tot,dfn[maxn],cnt,hi[maxn],Min;
struct edge{
int v,next;
}e[maxn*2];
void adde(int a,int b){e[tot].v=b,e[tot].next=head[a];head[a]=tot++;}
void dfs(int u,int h){
hi[u]=h;dfn[u]=1;
for(int i=head[u];i!=-1;i=e[i].next){
int v=e[i].v;
if(!dfn[v])dfs(v,h+1);
else if(hi[v]<hi[u]&&dfn[v]==1)Min=min(Min,hi[u]-hi[v]+1);
}dfn[u]=2;
}
int main(){
memset(head,-1,sizeof(head));
scanf("%d",&n);
for(int x,i=1;i<=n;i++){
scanf("%d",&x);adde(i,x);
}
int ans=1e9;
for(int i=1;i<=n;i++)if(!dfn[i]){
Min=1e9;
dfs(i,1);
ans=min(ans,Min);
}
printf("%d",ans);
return 0;
}