Tarjan缩点(复习整理)

  • 若两顶点间至少存在一条路径,则称两个顶点强连通。
  • 若有向图G中每两个顶点都强连通,则称G为强连通图。
  • 非强连通图中的极大强连通子图称为强连通分量。
  • Tarjan算法本质上是一种dfs
  • dfn[i]:dfs时被遍历的次序(时间戳)。
  • low[i]:最早能回溯到的栈中的点的时间戳。
  • stack[i]:判断i点是否在栈中。
  • dindex:时间戳,stop:栈顶。
  • 强连通分量中的点在栈中必定是连续一段。如果一个点x无法回溯到在它之前且在栈中的点,假设它的头顶上还有点,这些点的low值为x或者连接点(连接的连接…)的low为x(如果不是,1.是自己,在此之前已经弹出;2.是其它栈中点,首先不会是在x与它之间点y,因为y会比x更早被判断弹出(low[y]=dfn[y]),关于y的其它情况同上同下,如果是在x底下,那"x无法回溯到在它之前且在栈中的点"这一条件就不成立了)。这一切都源于tarjan算法本质为dfs!
    Tarjan缩点(复习整理)_第1张图片
  • 如果判断条件改为改成low[x]
  • tarjan算法
void tarjan(int x)
{
	dfn[x]=low[x]=++dindex;
	instack[x]=true;
	stap[++stop]=x;
	for(int i=last[x];i;i=e[i].next)
	{
		int v=e[i].v;
		if(!dfn[v])
		{
			tarjan(v);
			low[x]=min(low[x],low[v]);
		}
		else if(instack[v]&&low[x]>dfn[v])//经测试low[x]>low[v]也可,对应上述多次连接的情况
		low[x]=dfn[v];
	}
	int j;
	if(dfn[x]==low[x])
	{
		bcnt++;//缩点后的点编号
		do{
			 j=stap[stop--];
			belong[j]=bcnt;
			instack[j]=false;
			powe[bcnt]+=dian[j];//权值和
		}
		while(j!=x);
	}
}
  • 将缩点完成后的DAG图练成一个强连通图:假设入度为零的点数为a,出度为零的点数为b,所需要的最小边数为max(a,b);若原图已经强连通,所需要的边数为0.
  • tarjan给出了反拓扑序,不需要再额外topsort。

你可能感兴趣的:(图论,模板)