信息传递
题目描述
tarjan模板
点击查看代码
void tarjan(int x)
{
dfn[x]=low[x]=++num;
stk.push(x);
v[x]=1;
for(int i=h[x];i;i=nxt[i])
{
if(!dfn[to[i]])
{
tarjan(to[i]);
low[x]=min(low[x],low[to[i]]);
}
else if(v[to[i]])
{
low[x]=min(low[x],dfn[to[i]]);
}
}
if(low[x]==dfn[x])
{
sum=0;
int y;
++t;
do
{
y=stk.top();
stk.pop();
v[y]=0;
belong[y]=t;
sum++;
} while(y!=x);
if(sum>1) ans=min(ans,sum);
}
}
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
const int maxm=4e5+10;
int n,tot,num,t,ans=0x3f3f3f3f,belong[maxn],sum;
int h[maxn],nxt[maxm],to[maxm],dfn[maxn],v[maxn],low[maxn];
stack<int> stk;
void addedge(int x,int y)
{
to[++tot]=y;
nxt[tot]=h[x];
h[x]=tot;
}
void tarjan(int x)
{
dfn[x]=low[x]=++num;
stk.push(x);
v[x]=1;
for(int i=h[x];i;i=nxt[i])
{
if(!dfn[to[i]])
{
tarjan(to[i]);
low[x]=min(low[x],low[to[i]]);
}
else if(v[to[i]])
{
low[x]=min(low[x],dfn[to[i]]);
}
}
if(low[x]==dfn[x])
{
sum=0;
int y;
++t;//记录强连通分量个数
do
{
y=stk.top();
stk.pop();
v[y]=0;
belong[y]=t;//存y点属于哪个强连通分量
sum++;
} while(y!=x);
if(sum>1) ans=min(ans,sum);//如果是单点构成强连通分量就忽略
}
}
int main()
{
scanf("%d",&n);
int a;
for(int i=1;i<=n;i++)
{
scanf("%d",&a);
addedge(i,a);//建图
}
for(int i=1;i<=n;i++)
{
if(!dfn[i]) tarjan(i);//循环防止有多个图
}
printf("%d",ans);
return 0;
}