tarjan模板

信息传递

题目描述

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);
	}
}

本题要求求出最大强连通分量最小值(当然1不算)
所以当sum<2时跳过
还有一个地方就是本题没说所有点都是联通的,所以要循环一遍所有点
如果这个点的dfn值为零,说明这个点和之前搜过的点不在一个图中
最后上代码

#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;
}
posted @ 2024-03-15 16:51  晨曦ccx  阅读(33)  评论(0)    收藏  举报
浏览器标题切换
浏览器标题切换end