强连通缩点

强连通分量+缩点+拓扑排序 模板

(强连通建立新图)(tarjan找强连通分量)

#include 
#include 
#include 
#include 
typedef long long ll;
const constexpr int maxN = 1e6+3;
typedef int int_vec[maxN];
struct dag_helper
{
	int n,t;
	dag_helper(int _n=-1,int _t=0):n(_n),t(_t) {}
	bool operator<(const dag_helper& d) const
	{
		return t > d.t;
	}
};
int V,E;
int_vec head,to,next,dfn,low,belong,S,end;
int edge_count,time,scc_count,scc_edge_count,top,time_2;
dag_helper helper[maxN];
void init()
{
	std::fill_n(head,maxN,-1);
	std::fill_n(to,maxN,-1);
	std::fill_n(next,maxN,-1);
	std::fill_n(dfn,maxN,0);
	std::fill_n(low,maxN,0);
	std::fill_n(belong,maxN,-1);
	std::fill_n(end,maxN,0);
	scc_edge_count = 0;
	edge_count = 0;
	time = 0;
	scc_count = 0;
	top = -1;
	time_2 = 0;
}
void add(int u,int v)
{
	to[edge_count] = v;
	next[edge_count] = head[u];
	head[u] = edge_count++;
}
void scc_add(int u,int v)
{
	u += V;
	v += V;
	to[edge_count+scc_edge_count] = v;
	next[edge_count+scc_edge_count] = head[u];
	head[edge_count+scc_edge_count] = edge_count+scc_edge_count;
	++scc_edge_count;
}
void targan(int x)
{
	if (dfn[x]) return;
	dfn[x] = low[x] = ++time;
	S[++top] = x;
	for (int i=head[x];i>=0;i=next[i])
	{
		int y = to[i];
		if (!dfn[y])
		{
			targan(y);
			if (low[x] > low[y]) low[x] = low[y];
		}
		else if ((belong[y] == -1) and (low[x] > dfn[y])) low[x] = dfn[y];
	}
	if (dfn[x] == low[x])
	{
		while (true)
		{
			belong[S[top]] = scc_count;
			if (S[top--] == x) break;
		}
		++scc_count;
	}
}
void shrink()
{
	for (int i=0;i=0;j=next[j])
	{
		int t = to[j];
		if (belong[i] != belong[t]) scc_add(belong[i],belong[t]);
	}
}
void dfs(int x)
{
	for (int i=head[x];i>=0;i=next[i])
	{
		int y = to[i];
		if (!end[y]) dfs(y);
	}
	end[x] = ++time_2;
}
void dag()
{
	for (int i=0;i

注:

1.S为stack,可以用std::stack替代

2.helper最后的排序即为对应强连通分量的拓扑序(注意编号)

3.每个节点i属于belong[i]分量

4.节点编号、边编号从0开始,强联通节点编号从V开始,强联通边编号从E开始(初始时E == edge_count)

你可能感兴趣的:(强连通缩点)