链式向前星与Trajan算法

本文介绍了Trajan算法,一种用于求解强连通分量的方法。链式向前星是一种存储图的数据结构,便于遍历。内容包括加边操作、遍历过程以及算法的应用。同时推荐了两篇优快云博客,提供了更详细的解释和SPFA算法的扩展。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

模板:

加边:

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.youkuaiyun.com/Binary_Heap/article/details/78209086

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

 

Trajan算法

int  number[M],low[M],color[M],scc,cnt;  //萌新手打,请勿使用
stack<int> 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]<number[u]) 意思是有反向边
		{
			low[u]=min(low[u],number[v]);
		}
	}
	if(number[u]==low[u])
	{
		int x;
		++scc;                 //强连通分量个数 
		while(true)
		{
			x=s.pop();
			color[x]=scc;      //同scc对应同一个强分量; 
			size_[scc]++;	   //一个强连通分量的点的个数 
			if(u==x) break;
		}
	}
}

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

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

另附大佬理解:https://blog.youkuaiyun.com/mengxiang000000/article/details/51672725

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值