没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
题目:
Strong Connectivity
算法设计思想:
(冒泡法等方法)
(一)第一种算法
用邻接表表示的有向图
G
(邻接点表示表头结点所能够直接到达的结点),对其中的
所有结点进行两次深度优先搜索访问。对所有结点赋予三种颜色值:白、灰、黑;并且所有结
点的初始颜色均标记为白色,访问到的结点标记为灰色,访问完成后将结点标记为黑色。在
进行深度优先搜索时,另赋一个数组
f
记录所有结点访问完成的时间。第一遍深度优先搜索
找出从结点
u
出发所有能够到达的结点
v
的集合,并记录所有结点完成的时间
f[u]
。然后求
出
G
的转置
GT
(邻接点表示能够直接到达表头结点的结点),对
GT
按照访问结点的完成
时间顺序的相反顺序,进行第二遍深度优先搜索,从结点
u
能够到达的结点的集合中找出
所有能够到达结点
u
的结点集,该结点集就是一个强联通分支。
(二)第二种算法
为确定每一个强连通分支的根结点,定义一个数组
LOWLINK
:
LOWLINK[v]=MIN
(
{v}
U
|
从
v
的子孙结点出发存在到结点
w
的回边或交叉边,并且包含
结点
w
的强连通分支的根结点示
v
的一个祖先);
当且仅当
LOWLINK[v]=v
时,结点
v
是一个强连通分支的根结点。
而为求
LOWLINK
的值,定义方法
SEARCHC(v)
。
首先将所有结点标记为未访问(
NEW
),定义
COUNT
来记录深度优先搜索值,定义
数组
DFNUMBER
存储结点的深度优先搜索值,定义堆栈
STACK
以结点深度优先搜索中
被访问的顺序放置结点。
对于执行过
SEARCHC(v)
的结点标记为已访问(
OLD
)并将
v
压栈;访问结点
v
的邻
接表中的所有结点,若结点
w
标记为
NEW
就对其进行
SEARCHC(w)
,得其
LOWLINK
值
和
DFNUMBER
值,将
LOWLINK[v]
与
LOWLINK[w]
中的较小者赋值给
LOWLINK[v]
,否
则 , 如 果
DFNUMBER[w]< DFNUMBER[v]
并 且 结 点
w
在 栈 中 , 将
LOWLINK[v]
与
DFNUMBER [w]
中的较小者赋值给
LOWLINK[v]
;如果
LOWLINK[v]=DFNUMBER [v]
,
将结点
x
从栈中取出并打印,重复此操作直至
x=v
,打印强连通分支结束提示。
当图中只要还存在标记为
NEW
的结点时,就对该结点进行
SEARCH(v)
方法,这样就
将所有的强连通分支找到并将其所有结点打印出来。
算法分析:
(时间分析)
(
1
) 第一种算法
对于第一种算法,由于对每个接点都要访问一次,故而
DFS()
的时间复杂度为
T(v)
(
v
为结
点个数),其中并未包括
DFS_VISIT()
方法耗用的时间;由于没条边都要访问一次,故而
对于
DFS_VISIT()
方法的时间复杂度为
T(E)
(
E
为图中的边数)。综上深度优先搜索的时间
复杂度为
T(V+E)
。由于要进行两次深度优先搜索故时间复杂度为
2T(V+E)
。
(
2
) 第二种算法
对于一次调用
SEARCH(v)
,要对结点
v
的所有未访问过的邻接点
w
进行
SEARCH(w)
运算,
即需要遍访所有的结点和边一次,故算法时间复杂度为
T(V+E)
。
源代码:
(一)第一种算法
#ifndef GRAPH
#define GRAPH
#ifndef N
#define N 50
//
假定图中结点个数不大于
50
#endif
#include "stdafx.h"
#include "iostream.h"
//
结点结构体
typedef struct Vertex
{
int sign;//
图中结点的标号
struct Vertex *next;
}Vertex;
class Graphic
{
Vertex *Graph;//
图邻接表头
Vertex *GraphT;//
图的转置的邻接表头
int num;//
图中结点个数
int *father;//
存放
DFS
树中各结点父结点的标号,
-1
代表无父结点
int *fatherT;
int *color;//
记录结点颜色
int time;//
深度优先搜索时间戳
int *d;//
发现时间
int *f;//
完成时间
int *fT;//
按发现的后先顺序存储结点下标
public:
Graphic()//
构造一个有
n
个结点的图
{
int n;
do{
cout<<"
请输入结点个数
n:"<<endl;
cin>>n;
}while(n<0);
Graph=new Vertex[n];
GraphT=new Vertex[n];
father=new int[n];//
为存储父结点的指针分配空间
fatherT=new int[n];
color=new int[n];//
存放各结点的颜色值,
0
为白色,
1
为灰色,
2
为黑色
d=new int[n];
f=new int[n];
fT=new int[n];
num=n;
time=0;//
赋初始时间戳为
0
for (int i=0;i<n;i++)
{
// Graph[i]=new Vertex;
Graph[i].sign=i;
Graph[i].next=NULL;
GraphT[i].sign=i;
GraphT[i].next=NULL;
father[i]=-1;//
无父结点
fatherT[i]=-1;//
无父结点
color[i]=0;//
全部着为白色
d[i]=0;
f[i]=0;
fT=new int[n];
}
}
//
将标号为
j
的结点添加到结点
i
的邻接表中
,
表示从
i
指向
j
void add(int i,int j,Vertex *Graph)
{
Vertex *p=&Graph[i];
Vertex *q=new Vertex;
q->sign=j;
q->next=NULL;
while(p->next)
p=p->next;//
令
p
指向最后一个结点
p->next=q;
}
bool isedge_exist(int i,int j)//
判断边是否已经存在,存在返回
true
,否则返回
false
{
Vertex *p=Graph[i].next;
while(p)
{
if(p->sign!=j)
p=p->next;
else
break;
}
if(!p)
return false;
else
return true;
}
void input()//
从键盘输入图的边
{
char c;
int from,to;
剩余13页未读,继续阅读
资源评论
明之森
- 粉丝: 9
- 资源: 6
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功