【算法】设计算法求所有强连通分量的完整代码(kosaraju算法)

代码:

typedef struct anode {
    int adjvex;//该边的邻接点编号
    struct anode* nexarc;//指向下一条边的指针
    int weight;//该边的相关信息,比如权值
}arcnode;//边结点类型
typedef struct vnode {
    //InfoTyoe info; 顶点的其他信息
    arcnode* firstarc;//指向第一个边结点
}Vnode;//邻接表头结点类型
typedef struct {
    vnode adjlist[10000];//邻接表头结点数组
    int n, e;//图中顶点数n和边数e
}adjgraph;//完整的图邻接表类型
#define INF 1e6; 
#define maxn 1000; 
int visited[maxn];
stack<int>st;//全局栈,存放逆拓扑序列
void create(adjgraph*g,int A[8][8],int n,int e)
{
	g->e = e;
	g->n = n;
	arcnode*q;
	for(int i = 0;i < n;i++)
	for(int j = 0;j < n;j++)
	{
		if(A[i][j] != INF && i != j)
		{
			g->adjlist[i].firstarc->weight = A[i][j];
q = (arcnode*)malloc(sizeof(arcnode));
q->adjvex = j;
q->nexarc = g->adjlist[i].firstarc;//头插法
g->adjlist[i].firstarc = q;


		}
	}
}
void createReAdj(adjgraph*g,adjgraph*g2){
	//产生逆邻接表
	arcnode*q,*p;
	int i,w;

	g2 = (adjgraph*)malloc(sizeof(adjgraph));
	g2->n = g->n;
	for(int i = 0;i < g->n;i++)
	g2->adjlist[i].firstarc = NULL;
		for(int i = 0;i < g->n;i++)
		{
			p = g->adjlist[i].firstarc;
			while (p != NULL)
			{
			w = p->adjvex;//如果原图存在(i,w)
			q = (arcnode*)malloc(sizeof(arcnode));
			q->adjvex = i;
			q->weight = p->weight;
			q->nexarc = g2->adjlist[w].firstarc;
			g2->adjlist[w].firstarc = q;//生成一条(w,i)边
			
		p = p->nexarc;
			}
	
		}
}
//深度递归1 产生一个逆拓扑序列
void dfs1(adjgraph*g, int u)
{
	visited[u] = 1;
	//从u出发深度搜索
	arcnode* q;
	q = g->adjlist[u].firstarc;//指向u的第一个邻接点

while(q){
	int num = q->adjvex;
		if(visited[num]!=1)
		dfs1(g,num);
	q = q->nexarc;//指向下一个邻接点
		
	
	}
	st.push(u);//最后一步才将u入栈

}
//深度递归2 用于求一个强连通分量 ,其中一个数组component即一个强连通分量
void dfs2(adjgraph* g,int v,vector<int>&component)
{
	int w;
	arcnode*p;
	visited[v] = 1;
	p = g->adjlist[v].firstarc;
		component.push_back(num);
			st.pop();//每次递归都出栈中的一个元素,直到最后栈为空
	while(p)
	{
		int num = p->adjvex;
	
		if(!visited[num])
		{
		
		dfs2(g,num,component);
		}
		p = p->nexarc;
	}
}
void Kosaraju(adjgraph*g)
{
	//求g的强连通分量
	adjgraph*g1;
	vector<int>com;
	memset(visited,0,sizof(visited));
	for(int i = 0;i < g->n;i++)
	if(st.size() != g->n)//当st中元素个数小于顶点数目时
	dfs1(g,i);//第一步首先递归产生逆拓扑序列
	memset(visited,0,sizeof(visited));//再次恢复visited为未访问
	createReAdj(g,g1);//产生逆邻接表
	while(!st.empty())
	{
		//栈不空时循环
		int top1 = st.top();//取栈顶
		com.clear();//每次都清空vector数组
		print("顶点%d的强连通分量",top1);
		dfs2(g,top,com);
		for(int i = 0;i < com.size();i++)
		cout<<com[i]<<" ";//输出一个强连通分量
		cout<<endl;
	}
	detroy(g1);//销毁g1
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值