分析
tarjan算出全部的联通块,在求出联通块里最小的个数。
AC代码
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cctype>
#include <cmath>
#include <time.h>
using namespace std;
#define ms(a,b) memset(a,b,sizeof(a))
const int maxn=200010;
struct Edge{
int to,next;
}edge[maxn<<1];
int nedge,sum,dep,top,n,m,cnt;
int head[maxn],dfn[maxn],stack[maxn],low[maxn],od[maxn],vis[maxn],id[maxn];
int belong[maxn],block[maxn];
inline int read()
{
int X=0,w=0; char ch=0;
while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
return w?-X:X;
}
void add_edge(int a,int b)
{
edge[nedge]=(Edge){b,head[a]}; head[a]=nedge++;
}
void tarjan(int u)
{
dfn[u]=low[u]=++dep;
stack[top++]=u;
vis[u]=1;
for (int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if (!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else
{
if (vis[v]) low[u]=min(low[u],dfn[v]);
}
}
int j;
if (dfn[u]==low[u])
{
sum++;
do{
j=stack[--top];
belong[j]=sum;
vis[j]=0;
}
while (u!=j);
}
}
int main()
{
nedge=0;
ms(head,-1);
n=read();
for (int i=1;i<=n;i++)
{
int a=read();
add_edge(i,a);
}
for (int i=1;i<=n;i++)
{
if (!dfn[i]) tarjan(i);
}
for (int i=1;i<=n;i++)
{
block[belong[i]]++;
}
int ans=maxn;
for (int i=1;i<=sum;i++)
{
if (block[i]!=1) ans=min(block[i],ans);
}
printf("%d\n",ans);
return 0;
}