找不到文字的就放图了
题解
一开始想到很水的dfs(果然是因为最近常做淼题?)
结果wa一半的点,另一半刚好±1
经提示跑tarjan,找到最小的不是1的强联通分量
手工栈,手工栈,手工栈,学习了
#pragma comment(linker, "/STACK:102400000,102400000")
#include <stdio.h>
#include <cstring>
#include <stack>
using namespace std;
struct edge
{
int x,y,next;
}e[200005];
int n,t,ans=0x7fffffff;
int dfn[200005],low[200005],ls[200005];
stack<int>s;
int min(int x,int y)
{
return x<y?x:y;
}
void tarjan(int x)
{
int y;
dfn[x]=++t;
low[x]=t;
s.push(x);
for (int i=ls[x];i;i=e[i].next)
{
y=e[i].y;
if (!dfn[y])
tarjan(y),low[x]=min(low[x],low[y]);
else
low[x]=min(low[x],dfn[y]);
}
if (dfn[x]==low[x])
{
int cnt=0;
do
{
y=s.top();
s.pop();
cnt++;
}while(x!=y);
if (cnt!=1)
ans=min(ans,cnt);
}
}
int main()
{
int size=256<<20; // 256MB
char *p=(char*)malloc(size)+size;
__asm__("movl %0, %%esp\n"::"r"(p));
freopen("message.in","r",stdin);
freopen("message.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
e[i].x=i;
scanf("%d",&e[i].y);
e[i].next=ls[e[i].x];
ls[e[i].x]=i;
}
for (int i=1;i<=n;i++)
if (!dfn[i])
tarjan(i);
printf("%d\n",ans);
return 0;
}