基于visual Studio2013解决算法导论之050强连通分支




题目

强连通分支


解决代码及点评

// 强连通分支.cpp : 定义控制台应用程序的入口点。
//

#include<iostream>
#define MAX 100
using namespace std;

//深度搜索访问节点层次标志枚举变量
enum Color{white,gray,black};

//边端点结构体
struct edgeNode
{
	int no; //边尾端的序号
	char info; //边端的名称
	struct edgeNode * next; //下一个
};

//节点结构体
struct vexNode
{
	char info; //节点名称
	struct edgeNode *link; //与之相连的端点
};

//强连通子图的链表头结构体
struct StronConHead
{
	int num; // 强连通子图序号
	struct StronConNode *link; //此强连通子图的第一个节点
};

//
struct StronConNode
{
	int num; //一个强连通子图节点的序号
	char info; //一个强连通子图节点的名称
	struct StronConNode *next; //下一个
};

//深度搜索访问节点的开始/完成时间结构体
struct Time
{
	int num; //节点序号
	int time; //时间
};

//存储节点信息,adjlist1存储图,adjlist2存储图的转置
vexNode adjlist1[MAX],adjlist2[MAX];
//访问层次
//还没访问为white,访问了但是还没完成它的所有后裔的搜索为gray
//完成它的所有后裔的搜索为black
Color color[MAX];
//访问的开始时间
Time d[MAX];
//访问的完成时间
Time f[MAX];
//深度搜索时,访问过的节点标志
bool visited[MAX];
//con[j]是序号为j的强连通子图的链表头数组,
StronConHead con[MAX];


//建立邻接表存储与其转置
//adjlist1为节点集,adjlist2为图转置节点集,n为节点个数,e为边数目
void createGraph(vexNode *adjlist1,vexNode *adjlist2,int n,int e)
{
	int i;
	for(i=1;i<=n;i++)
	{
		cout<<"输入顶点值";
		cin>>adjlist1[i].info;
		adjlist2[i].info = adjlist1[i].info;
		adjlist1[i].link = NULL;
		adjlist2[i].link = NULL;
	}
	edgeNode *p1,*p2;
	int v1,v2;
	for(i=1;i<=e;i++)
	{
		cout<<"输入起点(节点序号)";
		cin>>v1;
		cout<<"输入终点(节点序号)";
		cin>>v2;
		//建立原图邻接表
		p1 = (edgeNode*)malloc(sizeof(edgeNode));
		p1->no = v2;
		p1->info = adjlist1[v2].info;
		p1->next = adjlist1[v1].link;
		adjlist1[v1].link = p1;
		//建立转置图邻接表
		p2 = (edgeNode*)malloc(sizeof(edgeNode));
		p2->no = v1;
		p2->info = adjlist2[v1].info;
		p2->next = adjlist2[v2].link;
		adjlist2[v2].link = p2;
	}
}

//深度优先搜索有向无权图
//adjlist1为原图的邻接表存储,time为一个全局时间戳,v是第几个节点
void DFS1(vexNode *adjlist1,int &time,int v)
{
	color[v] = gray;
	time += 1;
	d[v].num = v;
	d[v].time = time;
	edgeNode *p;
	p = adjlist1[v].link;
	while(p != NULL)
	{
		if(color[p->no]==white)
		{
			DFS1(adjlist1,time,p->no);
		}
		p = p->next;
	}
	color[v] = black;
	time += 1;
	f[v].num = v;
	f[v].time = time;
}

////降序排列第一次深度搜索各节点的完成时间
void fast_sort_f(Time *f,int begin,int end)
{
	if(begin<end)
	{
		int i = begin-1, j = begin;
		f[0] = f[end];
		while(j<end)
		{
			if(f[j].time>f[0].time)
			{
				i++;
				Time temp = f[i];
				f[i] = f[j];
				f[j] = temp;
			}
			j++;
		}
		Time temp1 = f[end];
		f[end] = f[i+1];
		f[i+1] = temp1;
		fast_sort_f(f,begin,i);
		fast_sort_f(f,i+2,end);
	}
}
//深度优先搜索有向无权图的转置图
//adjlist2为转置图的邻接表存储,con是序号为no的强连通子图的链表头数组,
//time为一个全局时间戳,v是第几个节点
void DFS2(vexNode *adjlist2,StronConHead *con,int &no,int v)
{
	visited[v] = true;
	StronConNode *p1 = (StronConNode*)malloc(sizeof(StronConHead));
	p1->info = adjlist2[v].info;
	p1->num = v;
	p1->next = con[no].link;
	con[no].link = p1;
	edgeNode *q1;
	q1 = adjlist2[v].link;
	while(q1 != NULL)
	{
		if(!visited[q1->no])
		{
			DFS2(adjlist2,con,no,q1->no);
		}
		q1 = q1->next;
	}
}

////打印各个强连通分支节点
//con是序号为no的强连通子图的链表头数组,no是强连通全局分支序号
void print_StronConCom(StronConHead *con,int &no)
{
	int i;
	StronConNode * p;
	for(i=1;i<no;i++)
	{
		cout<<"强连通分支"<<i<<":";
		p = con[i].link;
		while(p !=NULL)
		{
			cout<<"("<<p->num<<":"<<p->info<<") ";
			p = p->next;
		}
		cout<<endl;
	}
}
int main(int argc, char* argv[])
{
	int cases;
	cout<<"案例个数:";
	cin>>cases;
	while(cases--)
	{
		int n,e;
		cout<<"节点数:";
		cin>>n;
		cout<<"边数:";
		cin>>e;
		//访问节点的时间戳,全局变量
		int time = 0;
		//no是强连通全局分支序号,全局变量
		int no = 1;
		//访问标志清空与前驱节点都初始化为0
		int i;
		for(i=1;i<=n;i++) 
		{
			color[i] = white;
			visited[i] = false;
			con[i].link = NULL;
		}
		//创建邻接表
		createGraph(adjlist1,adjlist2,n,e);
		//第一次深度搜索,搜索原图
		for(i=1;i<=n;i++)
		{
			if(color[i]==white)
				DFS1(adjlist1,time,i);
		}
		//降序排列第一次深度搜索各节点的完成时间
		fast_sort_f(f,1,n);
		//第二次深度搜索,搜索原图的转置图
		for(i=1;i<=n;i++)
		{
			if(!visited[i])
			{
				DFS2(adjlist2,con,no,f[i].num);
				no += 1;
			}
		}
		//打印各个强连通分支节点
		print_StronConCom(con,no);
	}
	system("pause");
	return 0;
}



代码下载及其运行

代码下载地址:http://download.csdn.net/detail/yincheng01/6858815

解压密码:c.itcast.cn


下载代码并解压后,用VC2013打开interview.sln,并设置对应的启动项目后,点击运行即可,具体步骤如下:

1)设置启动项目:右键点击解决方案,在弹出菜单中选择“设置启动项目”


2)在下拉框中选择相应项目,项目名和博客编号一致

3)点击“本地Windows调试器”运行


程序运行结果









posted on 2014-01-17 21:39  三少爷的剑123  阅读(182)  评论(0编辑  收藏  举报

导航