因ppt太水 遂有此文

有向图

求强连通分量

点击查看代码

void tarjan(int x)
{
	dfn[x]=low[x]=++num;
	stk.push(x);
	f[x]=1;
	for(int i=head[x];i;i=net[i])
	{
		if(!dfn[to[i]])
		{
			tarjan(to[i]);
			low[x]=min(low[x],low[to[i]]);
		}
		else if(f[to[i]])
		{
			low[x]=min(low[x],dfn[to[i]]);
		}
	}
	if(low[x]==dfn[x])
	{
		int y;
		++t;
		do
		{
			y=stk.top();
			stk.pop();
			f[y]=0;
			belong[y]=t;
			vl[t]+=v[y];
		}while(y!=x);
	}
}

重建 缩点

点击查看代码


void reb()
{
	for(int i=1;i<=n;i++)
	{
		for(int j=head[i];j;j=net[j])
		{
			if(belong[i]!=belong[to[j]]) add1(belong[i],belong[to[j]]);
		}
	}
}

无向图

求割边

点击查看代码

//存边要从2开始存
void tarjan(int x,int in_edge)
{
	dfn[x]=low[x]=++num;
	for(int i=head[x];i;i=edge[i].next)
	{
		int y=edge[i].to;
		if(!dfn[y])
		{
			tarjan(y,i);
			low[x]=min(low[x],low[y]);
			if(low[y]>dfn[x])
			{
				bridge[i]=bridge[i^1]=1;
			}	
		}
		else if(i!=(in_edge^1))
		{
			low[x]=min(low[x],dfn[y]);
		}
	}
}

求割点

点击查看代码

void tarjan(int now)
{
	dfn[now]=low[now]=++num;
	int flag=0;  
	for(int i=head[now];i;i=edge[i].next)
	{
		int y=edge[i].to;
		if(!dfn[y])
		{
			tarjan(y);
			low[now]=min(low[now],low[y]);
			if(low[y]>=dfn[now])
			{
				flag++;
				if(now!=root||flag>1) cut[now]=1;
			}	
		}
		else
		{
			low[now]=min(low[now],dfn[y]);
		}
	}
}

求点双连通分量

点击查看代码

void tarjan(int now,int fa) 
{
	dfn[now]=low[now]=++num;
	stk.push(now);
	bool first =1;
	int son=0;
	for(int i=head[now];i;i=edge[i].next)
	{
		int to=edge[i].to;
		if(first&&to==fa)
		{
			first=0;
			continue;
		}
		if(!dfn[to])
		{
			son++;
			tarjan(to,now);
			low[now]=min(low[now],low[to]);
			if(dfn[now]<=low[to])
			{
				cut[now]=1;
				tot++;
				dslt[tot].push_back(now);
				int x;
				do
				{
					x=stk.top();
					stk.pop();
					dslt[tot].push_back(x);
				}while(x!=to);
			}
		}
		else low[now]=min(low[now],dfn[to]);
	}
	if(fa==-1&&son==1) cut[now]=0;
}

求边双连通分量

点击查看代码

// 需在dfs前求出所有的割边
//c[i]表示i属于第几个边双
void dfs(int x)
{
	c[x]=dcc;
	for(int i=head[x];i;i=edge[i].next) 
	{
		int y=egde[i].to;
		if(c[y]||bridge[i]) continue;
		dfs(y); 
	}
}
int main()
{
	for(int i=1;i<=n;i++)
	{
		if(!c[i]){
			++dcc;
			dfs(i);
		}
	}
 }