算法导论 强连通分量

#include <stdio.h>
#include <stdlib.h>

#define WHITE 0
#define GRAY 1
#define BLACK 2

//CNT用于编号TOPO序列,CNT_GROUP用于编号group
int CNT,CNT_GROUP;

//顶点类型,f是算导标准算法中的一个属性,这里其实可以省略
typedef struct
{
	int color;
	int group;
	char name;
	int f;
}Vertex,*pVertex;

//图类型,包含Topo排序数组
typedef struct 
{
	int v_n;
	pVertex *V;
	int **E;
	int *TopoOrder;
}Graph,*pGraph;

//根据算导中的图22-9进行初始化
pGraph initGraph()
{
	pGraph g = (pGraph)malloc(sizeof(Graph));
	g->v_n=8;
	g->TopoOrder=(int*)malloc(g->v_n*sizeof(int));
	pVertex v1=(pVertex)malloc(sizeof(Vertex));
	v1->name='a';
	v1->group=-1;
	v1->color=WHITE;
	v1->f=0;

	pVertex v2=(pVertex)malloc(sizeof(Vertex));
	v2->name='b';
	v2->group=-1;
	v2->color=WHITE;
	v2->f=0;

	pVertex v3=(pVertex)malloc(sizeof(Vertex));
	v3->name='c';
	v3->group=-1;
	v3->color=WHITE;
	v3->f=0;

	pVertex v4=(pVertex)malloc(sizeof(Vertex));
	v4->name='d';
	v4->group=-1;
	v4->color=WHITE;
	v4->f=0;

	pVertex v5=(pVertex)malloc(sizeof(Vertex));
	v5->name='e';
	v5->group=-1;
	v5->color=WHITE;
	v5->f=0;

	pVertex v6=(pVertex)malloc(sizeof(Vertex));
	v6->name='f';
	v6->group=-1;
	v6->color=WHITE;
	v6->f=0;

	pVertex v7=(pVertex)malloc(sizeof(Vertex));
	v7->name='g';
	v7->group=-1;
	v7->color=WHITE;
	v7->f=0;

	pVertex v8=(pVertex)malloc(sizeof(Vertex));
	v8->name='h';
	v8->group=-1;
	v8->color=WHITE;
	v8->f=0;

	g->V = (pVertex *)malloc(g->v_n*sizeof(Vertex));
	g->V[0]=v1;
	g->V[1]=v2;
	g->V[2]=v3;
	g->V[3]=v4;
	g->V[4]=v5;
	g->V[5]=v6;
	g->V[6]=v7;
	g->V[7]=v8;

	g->E=(int**)malloc(g->v_n*sizeof(int*));
	for(int i=0;i<g->v_n;i++)
	{
		g->E[i]=(int*)malloc(g->v_n*sizeof(int));
	}
	for(int i=0;i<g->v_n;i++)
	{
		for(int j=0;j<g->v_n;j++)
		{
			g->E[i][j]=0;
		}
	}
	g->E[0][1]=1;
	g->E[1][2]=1;
	g->E[1][4]=1;
	g->E[1][5]=1;
	g->E[2][3]=1;
	g->E[2][6]=1;
	g->E[3][2]=1;
	g->E[3][7]=1;
	g->E[4][0]=1;
	g->E[4][5]=1;
	g->E[5][6]=1;
	g->E[6][5]=1;
	g->E[6][7]=1;
	g->E[7][7]=1;

	return g;
}

//矩阵转置,除了取反向边,其余全部复制
pGraph transposeGraph(pGraph x)
{
	pGraph g = (pGraph)malloc(sizeof(Graph));
	g->v_n=x->v_n;
	g->TopoOrder=(int*)malloc(g->v_n*sizeof(int));
	g->V = (pVertex *)malloc(g->v_n*sizeof(Vertex));
	for(int i=0;i<g->v_n;i++)
	{
		pVertex v=(pVertex)malloc(sizeof(Vertex));
		v->color=x->V[i]->color;
		v->group=x->V[i]->group;
		v->name=x->V[i]->name;
		v->f=x->V[i]->f;
		g->V[i]=v;
	}
	for(int i=0;i<g->v_n;i++)
	{
		g->TopoOrder[i]=x->TopoOrder[i];
	}
	g->E=(int**)malloc(g->v_n*sizeof(int*));
	for(int i=0;i<g->v_n;i++)
	{
		g->E[i]=(int*)malloc(g->v_n*sizeof(int));
	}
	for(int i=0;i<g->v_n;i++)
	{
		for(int j=0;j<g->v_n;j++)
		{
			if(x->E[i][j]==1)
				g->E[j][i]=1;
			else
				g->E[j][i]=0;
		}
	}
	return g;
}

void dfsVisit(pGraph g,int v)
{
	g->V[v]->color=GRAY;
	for(int i=0;i<g->v_n;i++)
	{
		if(g->E[v][i]==1)
		{
			if(g->V[i]->color==WHITE)
				dfsVisit(g,i);
		}
	}
	g->V[v]->color=BLACK;
	g->V[v]->f=CNT;
	g->TopoOrder[CNT]=v;
	CNT++;
}

void dfs(pGraph g)
{
	for(int i=0;i<g->v_n;i++)
	{
		g->V[i]->color=WHITE;
	}
	CNT=CNT_GROUP=0;
	for(int i=0;i<g->v_n;i++)
	{
		if(g->V[i]->color==WHITE)
			dfsVisit(g,i);
	}
}

void dfsVisit2(pGraph g,int v)
{
	g->V[v]->color=GRAY;
	for(int i=0;i<g->v_n;i++)
	{
		if(g->E[v][i]==1)
		{
			if(g->V[i]->color==WHITE)
				dfsVisit2(g,i);
		}
	}
	g->V[v]->color=BLACK;
	g->V[v]->f=CNT;
	g->V[v]->group=CNT_GROUP;
	CNT++;
}

void dfs2(pGraph g)
{
	for(int i=0;i<g->v_n;i++)
	{
		g->V[i]->color=WHITE;
	}
	CNT=CNT_GROUP=0;
	for(int i=g->v_n-1;i>=0;i--)
	{
		int j=g->TopoOrder[i];
		if(g->V[j]->color==WHITE)
		{
			dfsVisit2(g,j);
			CNT_GROUP++;
		}
	}
}

void printGroup(pGraph g)
{
	for(int i=0;i<g->v_n;i++)
	{
		printf("%c:%d,",g->V[i]->name,g->V[i]->group);
	}
	printf("\n");
}

void printTopo(pGraph g)
{
	for(int i=g->v_n-1;i>=0;i--)
	{
		int j=g->TopoOrder[i];
		printf("%c:%d,",g->V[j]->name,i);
	}
	printf("\n");
}

void printE(pGraph g)
{
	for(int i=0;i<g->v_n;i++)
	{
		for(int j=0;j<g->v_n;j++)
		{
			printf("%d ",g->E[i][j]);
		}
		printf("\n");
	}
}

//分两遍DFS,第一遍取得原图Topo序列,第二遍根据Topo序列遍历顶点,取得强连通分量
//为什么两遍可以取得强连通分量,请参考http://blog.sina.com.cn/s/blog_4dff87120100r58c.html
void main()
{
	pGraph g=initGraph();	
	dfs(g);
	//printE(g);
	printTopo(g);
	pGraph gt=transposeGraph(g);
	dfs2(gt);
	//printE(gt);
	printGroup(gt);
	getchar();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值