有向图关键路径问题+三种算法求解

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

#include
#include
#include


#include
#include
#include
#include
#include
#include
#include


//***************************************************邻接表实现**********************************//
#define MAX 20
#define MVNum 20

typedef int VertexType1;//宏定义
typedef int Vertexid;

typedef struct node{//结构体
int adjvex;
int dut;
struct node *next;
}EdgeNode;

typedef struct vnode{
VertexType1 vertex ;
Vertexid id;
EdgeNode *link;
}VNode,Adjlist[MAX];

typedef Adjlist AOELGraph;

void CreateGraph(AOELGraph &GL,int n,int e)
{
/*n为顶点数,e为图的边数*/
int i,j,k,l;
EdgeNode *p;

cout<<"请读入顶点信息和入度\n";
for(i=1;i<=n;i++)
{
//建立顶点表
cin>>GL[i].vertex;
cin>>GL[i].id;
GL[i].link=NULL;
}
cout<<"输入边的i,j和边上的权值w:\n";
for(k=1;k<=e;k++)
{
cin>>i>>j>>l;
p=(EdgeNode *)malloc(sizeof(EdgeNode));//生成新的边表结点
p->adjvex=j; //将邻接点序号j赋值给新结点的邻接电域
p->dut=l;
p->next=GL[i].link;
GL[i].link=p; //将新结点插入到顶点Vi的边表头部
}
}


void CriticalPath(AOELGraph dig,int n,int e1)
{

int i,j,m,front,rear;
int k=0,x=0;
int flg[MVNum];


int ve[MVNum],vl[MVNum],e[MVNum],l[MVNum];

int tpord[MVNum];

EdgeNode *p;

for(i=1;i<=n;i++)
ve[i]=vl[i]=0;

front=0;
rear=0;

for(i=1;i<=n;i++)
{

if(dig[i].id==0)
{
rear++;
tpord[rear]=i;

}

}

m=0;

while(front!=rear)
{
front++;
j=tpord[front];
m++;

p=dig[j].link;

while(p!=NULL)
{

k=p->adjvex;
dig[k].id=dig[k].id-1;

if(ve[j]+p->dut>ve[k])
ve[k]=ve[j]+p->dut;
if(dig[k].id==0)
{

rear++;tpord[rear]=k;

}
p=p->next;

}
}

if(m{

cout<<"网中有回路!不能拓扑排序"<
return;

}

for(i=1;i<=n;i++)
vl[i]=ve[i];

for(i=n-1;i>=1;i--)
{
j=tpord[i];
p=dig[j].link;
while(p!=NULL)
{
k=p->adjvex;

if((vl[k]-p->dut)>vl[j])

vl[j]=vl[k]-p->dut;

p=p->next;

}
}

i=0;

for(j=1;j<=n;j++)
{

p=dig[j].link;

while(p!=NULL)
{
k=p->adjvex;
i++;

e[i]=ve[j];
l[i]=vl[k]-p->dut;

cout<<"顶点 "<
if(l[i]==e[i])
{cout<<"是关键活动"<else
{cout<<"不是关键活动"<p=p->next;

}

}
cout<<"这是邻接表存储结构实现"<}

//***************************************************邻接矩阵实现**********************************//


typedef struct ArcCell{
int adj;/*顶点关系类型,用1表示相邻,0表示不相邻*/
}ArcCell,**AdjMatrix;/*邻

接矩阵*/

typedef struct type{
char data[3];/*顶点值*/
int info;/*弧的长度*/
struct type *next;/*顶点的下一个指针*/
}VertexType;

typedef struct{
VertexType *vexs;/*顶点向量*/
AdjMatrix arcs;/*邻接矩阵*/
int vexnum,arcnum;/*图的顶点数和边数*/
}MGraph;


/* *******************/
typedef int Status;
#define STACK_INIT_SIZE 50
typedef int ElemType;

typedef struct STACK /*定义栈类型*/
{
ElemType *base;
ElemType *top;
int stacksize;
int length;
}SqStack,*Stack;

void InitStack(Stack *S) /*初始化栈*/
{

*S=(SqStack *)malloc(sizeof(SqStack));
(*S)->base=(ElemType *)malloc(STACK_INIT_SIZE*sizeof(ElemType));
if(!(*S)->base)exit(-1);
(*S)->top=(*S)->base;
(*S)->stacksize=STACK_INIT_SIZE;
(*S)->length=0;
}


Status DestroyStack(Stack *S) /* 销毁栈*/
{

free((*S)->base);
free((*S));
return 1;
}


Status StackEmpty(SqStack S) /*判断栈空否*/
{

if(S.top==S.base) return 1;
else
return 0;
}


void Push(Stack *S,ElemType e) /*把数据压入栈*/
{

if((*S)->top - (*S)->base>=(*S)->stacksize)
{
(*S)->base=(ElemType *) realloc((*S)->base,
((*S)->stacksize + 10) * sizeof(ElemType));
if(!(*S)->base)exit(-1);
(*S)->top=(*S)->base+(*S)->stacksize;
(*S)->stacksize +=10;
}

*((*S)->top++)=e;
++(*S)->length;

}



Status Pop(Stack *S,ElemType *e)/*删除栈顶元素*/
{

if((*S)->top==(*S)->base) return 0;
*e=*((*S)->top-1);
--(*S)->length;
(*S)->top--;
return 1;

}


/* ******************** */
void InitGraph(MGraph *G)/*初始图*/
{
int i,nu,mu;
printf("\n输入顶点的个数和(边)弧的个数:");
scanf("%d%d",&nu,&mu);
G->arcs=(ArcCell **)malloc(nu*sizeof(ArcCell *));
for(i=0;iG->arcs[i]=(ArcCell *)malloc(nu*sizeof(ArcCell));
G->vexs=(VertexType *)malloc(nu*sizeof(VertexType));/*分配顶点空间*/
G->vexnum=nu;G->arcnum=mu;/*图的顶点数和边数*/

}
void DestroyGraph(MGraph *G)/* 销毁图*/
{
int i;
free(G->vexs);
for(i=0;ivexnum;i++)
free(G->arcs[i]);

}


void InsertGraph(MGraph *G,int i,VertexType e)
{

if(i<0||i>G->vexnum) return;
G->vexs[i].next=e.next;
G->vexs[i].info=;
strcpy(G->vexs[i].data,e.data);

}



int Locate(MGraph G,VertexType v1)/*确定v1在图顶点中的位置*/
{

int i;
for(i=0;iif(strcmp(v1.data,G.vexs[i].data)==0) return i;
return -1;

}


void CreateUND(MGraph *G)/*采用数组(邻接矩阵)和邻接表表示无向图*/
{

int i,j,k,*p,d,w;
VertexType v1,v2,*q2,*q;

p=(int *)malloc(G->vexnum*sizeof(int));

for(i=0;ivexnum;i++) p[i]=0;
for(i=0;ivexnum;++i)/*初始邻接表*/
{
for(j=0;jvexnum;++j) G->arcs[i][j].adj=0;
}
printf("\n");

printf("按顺序输入顶点(方向)和它们的间长度以及终点:如 'v1 3 v2 ' : \n");
for(k=0;karcnu

m;++k)
{
printf("输入第 %d 条弧: \n",k+1);
d=0;
scanf("%s%d%s",v1.data,&w,v2.data);/*输入相邻的两个点值*/

i=Locate(*G,v1);
j=Locate(*G,v2);/*用i 和j来确定它们的位置*/

G->arcs[i][j].adj=1;

q2=(VertexType *)malloc(sizeof(VertexType));/*分配一个空间*/
strcpy(q2->data,
G->vexs[j].data);q2->info=w;

q2->next=NULL;/*以便连接在每个顶点后*/

if(p[i]==0) {
G->vexs[i].next=q2;p[i]++;
}/*i顶点后面还没有*/
else {
q=&(G->vexs[i]);/*i顶点后面有了*/
while(d!=p[i]) {d++;q=q->next;
}/*指到最后一个*/
p[i]++;
q->next=q2;/*接在最后*/

}

}

free(p);
}



void FindInDegree(MGraph G,int *indegree)/*对各顶点求入度,邻接矩阵的列*/
{
int i,j;
for(i=0;ifor(j=0;jif(G.arcs[j][i].adj==1) indegree[i]++;
}



int *ve,*vl;/*最早发生时间和最迟发生时间数组,全局的*/
int TopologicalOrder(MGraph G,Stack *T)/*有向图采用邻接表存储结构,无回路返回1*/
{

Stack S;
int i,k,count,*indegree;
VertexType *p;

indegree=(int *)malloc(G.vexnum*sizeof(int));/*度数组空间*/
ve=(int *)malloc(G.vexnum*sizeof(int));/*最早发生时间的数组空间*/

for(i=0;iindegree[i]=0;/*初始化*/

for(i=0;ive[i]=0;/*初始化*/

FindInDegree(G,indegree);/*求各点入度*/

InitStack(&S);/*初始化栈*/
InitStack(T);

for(i=0;iif(!indegree[i]) Push(&S,i);/*入度为0进栈*/

count=0;/*对输出顶点计数*/
while(!StackEmpty(*S))
{
Pop(&S,&i);/*拿出入度为0 的*/
Push(T,i);/*i号顶点入T栈*/
++count;/*计数*/
p=G.vexs[i].next;/*此层的下一个邻点*/
while(p)
{
k=Locate(G,*p);/*上面这个邻点的位置*/
if(!(--indegree[k])) Push(&S,k);/*减一后为0就入栈*/
if(ve[i]+p->info>ve[k]) ve[k]=ve[i]+p->info;/*在它的所有邻点中找出能使最大*/
p=p->next;/*这一层的其它邻点*/

}

}

DestroyStack(&S);
free(indegree);
if(countelse return 1;

}


int CriticalPath(MGraph G)/*G为有向网,输出G的各项关键活动*/
{

Stack T;
int j,k,dut,e1,e2;
char tag;
VertexType *p;

if(!TopologicalOrder(G,&T)) return 0;/*有回路就不做*/
vl=(int *)malloc(G.vexnum*sizeof(int));/*最迟发生时间数组空间*/
for(j=0;jvl[j]=ve[j];
while(!StackEmpty(*T))/*按拓扑逆序求各事件的 vl 值*/
{
Pop(&T,&j);/*从最后一个开始*/
p=G.vexs[j].next;
while(p)
{k=Locate(G,*p);/*邻点的位置*/
dut=p->info;/*两点间的长度*/
if(vl[k]-dut>vl[j]) vl[j]=vl[k]-dut;/*比较它的所有邻点中得到时间最迟的*/
p=p->next;

}
}

for(j=0;jprintf("事件

%s 的最早和最迟发生时间分别为 %d 和 %d\n",G.vexs[j].data,ve[j],vl[j]);
printf("关键活动为:\n");
for(j=0;j{
p=G.vexs[j].next;/*每个事件要依赖它的邻点才可知是否最早=最迟*/
while(p)
{
k=Locate(G,*p);/*邻点的位置*/
dut=p->info;/*弧长*/
e1=ve[j];e2=vl[k]-dut;/*如果最早开始时间=最迟开始时间,最迟为邻点减去弧长*/
if(e1==e2) tag='*';
else tag=' ';
if(tag=='*')
printf("*%s* 到 *%s* 长度为*%d* 发生时间为 *%d*\n",G.vexs[j].data,G.vexs[k].data,dut,e2);
p=p->next;

}
}

free(vl);free(ve);DestroyStack(&T);
cout<<"这是邻接矩阵存储结构实现"<return 1;

}



//****************************************深度遍历实现************************************//

#define MAX_VERTEX_NUM 20
#define MAX_NAME 4
// ********************表结点******************************
struct ArcNode
{
int adjvex; // 该弧所指向的顶点的位置
ArcNode *nextarc; // 指向下一条弧的指针
int info; // 网的权值
};

//*********************头结点*******************************
typedef struct
{
int data; // 顶点信息
ArcNode *firstarc; // 第一个表结点的地址,指向第一条依附该顶点的弧的指针
}AdjList[MAX_VERTEX_NUM];

//*********************图结构*******************************
struct ALGraph
{
AdjList vertices;//头结点数组
int vexnum,arcnum; // 图的当前顶点数和弧数

};




//********************返回顶点在图中位置 *****************************

int LocateVex(ALGraph G,int u)
{
int i;
for(i=0;iif(u==G.vertices[i].data)
return i;
return -1;
}



//*************/ 采用邻接表存储结构,构造图G*******************

int CreateGraph(ALGraph &G)
{
int i,j,k;
int w; // 权值
int va,vb;
ArcNode *p;


cout<<"请输入图的顶点数,边数: "<cin>>G.vexnum>>G.arcnum;

cout<<"请输入顶点的值:";
for(i=0;i{
cin>>G.vertices[i].data;
G.vertices[i].firstarc=NULL;
}

cout<<"请顺序输入每条弧(边)的弧尾和弧头以及权(以空格作为间隔):"<
for(k=0;k{

cin>>va>>vb>>w;

i=LocateVex(G,va); // 弧头
j=LocateVex(G,vb); //弧尾

p=(ArcNode*)malloc(sizeof(ArcNode));

p->adjvex=j;

p->info=w;

p->nextarc=G.vertices[i].firstarc; // 插在表头
G.vertices[i].firstarc=p;

}

cout<<"邻接表为:"<for(i=0;i{
cout< ";
for(p=G.vertices[i].firstarc;p;p=p->nextarc)
cout<< G.vertices[p->adjvex].data<<" --> ";
cout<<"^^"<}

return 0;
}



//************ 求顶点的入度*******************

void FindIndeg

ree(ALGraph G,int *indegree)
{
int i;
ArcNode *p;

for(i=0;iindegree[i]=0; // 赋初值

for(i=0;i{
p=G.vertices[i].firstarc;
while(p)
{
indegree[p->adjvex]++;
p=p->nextarc;
}
}
}



//*********************************利用深度优先遍历求网的关键路径*******************************//

int ve1[20];
int vl1[20];



void DFS1(ALGraph G,int i,int *indegree)
{
ArcNode *p;
int dut=0;
if(!indegree[i]) ve1[i]=0;

for(p=G.vertices[i].firstarc;p;p=p->nextarc)
{
dut=p->info;
if(ve1[i]+dut>ve1[p->adjvex])
ve1[p->adjvex]=ve1[i]+dut;
DFS1(G,p->adjvex,indegree);
}
}//DFS1


void DFS2(ALGraph G,int i)
{
ArcNode *p;
int dut=0;
if(!G.vertices[i].firstarc) vl1[i]=ve1[i];
else
{
for(p=G.vertices[i].firstarc;p;p=p->nextarc)
{
DFS2(G,p->adjvex);
dut=p->info;
if(vl1[p->adjvex]-dutvl1[i]=vl1[p->adjvex]-dut;
}

}//else

}//DFS2



void Critical_Path(ALGraph G)
{
int indegree[20];
ArcNode *p;
int path[20];
int x=0;
int i;
int e;
int l;

for(i=0;i{
ve1[i]=0;
vl1[i]=32767;
}// 赋初值

FindIndegree(G,indegree);

/*for(i=0;icout<*/


for(i=0;iif(!indegree[i]) DFS1(G,i,indegree); //第一次深度优先遍历:建立ve
/*for(i=0;icout<*/
cout<
for(i=0;iif(!indegree[i]) DFS2(G,i); //第二次深度优先遍历:建立vl
/*for(i=0;icout<*/
cout<
for(i=0;i{
for(p=G.vertices[i].firstarc;p;p=p->nextarc)
{

e=ve1[i];
l=vl1[p->adjvex]-p->info;

if(e==l)
cout<<"活动从顶点 "<adjvex].data<<"是关键活动"
<<" 活动持续时间为:"<< p->info<}
}

cout<<"这是深度遍历算法实现"<
}




//***********************************************main函数***************************************//

void main()
{
int M;
char password[20];
char password1[20];
strcpy(password,"123456");

do{
cout<<"请输入密码:"<cin>>password1;

}while(strcmp(password,password1));
cout<<"密码正确!"<cout<<"o(∩_∩)o...哈哈,欢迎进入!……"<cout<<"任意键继续……"<getch();
cout<while(1)
{
cout<cout<邻接表实现 | "<cout<邻接矩阵实现 | "<cout<深度遍历实现 | "<cout<<

setw(60)<<"| 4>退出 | "<cout<
cout<<"请输入以上选择:";

do{
cin>>M;
}while(M<1||M>4);


if(M==1)
{
int n,e;
AOELGraph GL;

cout<<"输入顶点数目和边数:"<cin>>n>>e;
CreateGraph(GL,n,e);
CriticalPath(GL,n,e);

}
if(M==2)
{
MGraph G;
VertexType e,*p;
int i;
InitGraph(&G);
printf("顶点值: \n");
for(i=0;i{scanf("%s",e.data);e.next=NULL;=9999;InsertGraph(&G,i,e);}
CreateUND(&G);/*构造图结构*/
printf("邻接表为:\n");
for(i=0;i{printf(" *%s* ",G.vexs[i].data);p=G.vexs[i].next;
while(p) {printf(" *%s* ",p->data);p=p->next;}
printf("\n");
}
getch();/*暂停*/
CriticalPath(G);/*关键活动函数*/
DestroyGraph(&G);/*销毁图*/
getch();
}

if(M==3)
{
ALGraph G;
CreateGraph(G);

Critical_Path(G);
}


if(M==4)
return;

cout<
}

}






相关文档
最新文档