tarjan全家桶

tarjan

1.点强连通分量

单向边

int n,m;
int co[N],col;
int dfn[N],low[N],tim;
int top,st[N];
void tarjan(int x)
{
	dfn[x]=low[x]=++tim;
	st[++top]=x;
	for(int i=h[x],v;i;i=e[i].nt)
	{
		if(!dfn[v=e[i].to])
		{
			tarjan(v);
			low[x]=min(low[x],low[v]);
		}
		else if(!co[v])low[x]=min(low[x],dfn[v]);
	}
	if(dfn[x]==low[x])
	{
		co[x]=++col;
		while(st[top]!=x)co[st[top--]]=col;
		top--;
	}
}
signed main()
{
	n=read();m=read();
	for(int i=1;i<=m;i++)
	{
		int x=read(),y=read();
		add(x,y);
	}
	for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);
    //.....
	return 0;
}

双向边直接看块数即可

2.割点

1.双向边

int dfn[N],low[N],tim;
bool flag[N];
void tarjan(int x,int fa)
{
	dfn[x]=low[x]=++tim;
	int child=0;
	for(int i=h[x],v;i;i=e[i].nt)
	{
		if(!dfn[v=e[i].to])
		{
			tarjan(v,x);
			low[x]=min(low[x],low[v]);
			if(low[v]>=dfn[x]&&x!=fa)flag[x]=1;
			if(x==fa)child++;
		}
		else low[x]=min(low[x],dfn[v]);
	}
	if(child>1&&x==fa)flag[x]=1;
}

3.割边

1.双向边

struct edge
{
	int nt,to;
}e[N<<1];
int h[N],id=1;//id 赋初值为 1 !!! 
inline void add(const int x,const int y){e[++id].to=y;e[id].nt=h[x];h[x]=id;}
int n,m;
bool cut[M],vis[N];
int tim,dfn[N],low[N];
int co[N],col;
void tarjan(int x,int fa)//x 上一条边 
{
	dfn[x]=low[x]=++tim;
	for(int i=h[x],v;i;i=e[i].nt)
	{
		if(!dfn[v=e[i].to])
		{
			tarjan(v,i);
			low[x]=min(low[x],low[v]);
			if(low[v]>dfn[x])cut[i]=cut[i^1]=1;
		}
		else if(i!=(fa^1))low[x]=min(low[x],dfn[v]);
	}
}
void dfs(int x)
{
	co[x]=col;
	for(int i=h[x],v;i;i=e[i].nt)
	{
		if(cut[i]||co[v=e[i].to])continue;
		dfs(v);
	}
}
signed main()
{
	n=read();m=read();
	for(int i=1;i<=m;i++)
	{
		int x=read(),y=read();
		add(x,y);add(y,x);//双向边 
	}
	for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i,0);
	for(int i=1;i<=n;i++)if(!co[i])++col,dfs(i);//割边之后连通块 (check ans) 
	
	for(int i=1;i<=n;i++)printf("%lld ",co[i]);
	
	return 0;
}

圆方树 点双

struct edge
{
	int nt,to;
}e[M],e1[M];
int h[N],id,h1[M],id1;
inline void add(const int x,const int y){e[++id].to=y;e[id].nt=h[x];h[x]=id;}
inline void add1(const int x,const int y){e1[++id1].to=y;e1[id1].nt=h1[x];h1[x]=id1;}
int n,m,q,tot;//tot>n
int dfn[N],low[N],tim;
int st[N],top;
inline void tarjan(int x,int ffa)
{
//	putchar('A');	
//	write(x);putchar(' ');printf("%d",ffa);puts("");
	dfn[st[++top]=x]=low[x]=++tim;
	for(int i=h[x],v;i;i=e[i].nt)
	{
		if(!dfn[v=e[i].to])
		{
			tarjan(v,x),low[x]=mmin(low[x],low[v]);
			if(low[v]>=dfn[x])
			{
				++tot;
				add1(tot,x);add1(x,tot);
				while(st[top+1]^v)add1(tot,st[top]),add1(st[top--],tot);
			}
		}
		else if(v^ffa)low[x]=mmin(low[x],dfn[v]);
	}
}
posted @ 2023-09-25 19:24  m0m0m  阅读(23)  评论(0)    收藏  举报