链式向前星与Trajan算法

模板:

加边:

struct node{
    int to,next,w;
}edge[1000];
int head[1000],cnt;
void add(int u,int v,int w)
{
    ++cnt;
    edge[cnt].to = v;
    edge[cnt].next = head[u];
    edge[cnt].w = w;
    head[u] = cnt;
}

e[i].to是指第i条边的终点,e[i].next是指与第i条边同起点(即u)的下一条边的储存下标(0时退出),e[i].w即第i条边的权重,head[u]是指u为起点的存储下标。

遍历:(遍历以u为起点的边)

for(i=head[u];i;i=edge[i].next)

i开始为第一条边,每次指向下一条(以0为结束标志)  (若下标从0开始,next应初始化-1)

假设输入1 2; 1 3; 1 5,即head一直更新,head[1] = 1;head [1] = 2;head[1] = 3,访问时其实是倒着访问的,先访问edge[3],然后i更新为edge[i].next即前一个head[1]即2,访问edge[2],再然后i更新为1,访问edge[1]。

推荐博客:https://blog.csdn.net/Binary_Heap/article/details/78209086

比较详细,也有SPFA的拓展。

 

Trajan算法

int  number[M],low[M],color[M],scc,cnt;  //萌新手打,请勿使用
stack s;
void dfs(int u)
{
	s.push(u)               //点入栈 
	number[u]=low[u]=++cnt;     //时间戳
	int v;
	for(i=head[u];i;i=edge[i].next)
	{
		v=edge[i].to;
		if(!number[v])         //点v有没有访问过,没有就从这里dfs 
		{
			dfs(v);
			low[u]=min(low[u],low[v]);
		}
		else if(!color[u])  //或者(number[v]

Trajan算法求强连通数,缩点,割点。

number[]是指访问的点的标号,low[]是指能到达或者子代能到达的最早结点标号,color[]标记同一个强连通分量,size_[]是一个强连通分量的点的个数。scc即强连通分量个数。

另附大佬理解:https://blog.csdn.net/mengxiang000000/article/details/51672725

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