#include<stdio.h>
#include<stdlib.h>
#define MAX_VERTEX_NUM 20//顶点最大个数
typedef int Status;//函数的类型,其值是函数结果状态代码
typedef char VertexType;//顶点元素的类型
typedef int ElemType;
typedef struct ArcNode
{
int adjvex;//该弧所指的顶点的位置
struct ArcNode *nextarc;//指向下一条狐的指针
int weight;//边的权
}ArcNode;//表的结点
typedef struct Vnode
{
VertexType data;
ArcNode *firstarc;
}VNode,AdjList[MAX_VERTEX_NUM];
typedef struct
{
AdjList vertices;
int vexnum,arcnum;
int kind;//图的种类
}ALGraph;
typedef struct SqStack
{
ElemType elem[MAX_VERTEX_NUM];
int top;
}SqStack;
//初始化栈
void InitStack(SqStack &S)
{
S.top=-1;
}
//判断栈空否,1为空
Status StackEmpty(SqStack S)
{
if(S.top==-1)
return 1;
else
return 0;
}
//入栈
Status Push(SqStack &S,ElemType e)
{
if(S.top==MAX_VERTEX_NUM-1)
return 0;
S.elem[++S.top]=e;
return 1;
}
//栈顶元素出栈
Status Pop(SqStack &S,ElemType *e)
{
if(S.top==-1)
return 0;
*e=S.elem[S.top--];
return 1;
}
//返回顶点v在图顶点向量中的位置
int LocateVex(ALGraph G,char v)
{
int i;
for(int i=0;v!=G.vertices[i].data&&i<G.vexnum;++i);
if(i>=G.vexnum)
return -1;
return i;
}
//建立邻接表
void creatDN(ALGraph &G)
{
int i,j,w;
char v1,v2;
ArcNode *s;
printf("输入图的顶点数:");
scanf("%d",&G.vexnum);
printf("输入图的边数:");
scanf("%d",&G.arcnum);
for(i=0;i<G.vexnum;i++)
{
printf("输入第%d的顶点的信息:",i+1);
scanf("%s",&G.vertices[i].data);
G.vertices[i].firstarc=NULL;
}
for(int i1=0;i1<G.arcnum;i1++)//该弧所指的顶点的位置
{
printf("输入第%d个活动的先序顶点:",i1+1);
scanf("%s",&v1);
printf("输入第%d个活动的后序顶点:",i1+1);
scanf("%s",&v2);
printf("输入这个活动的时间:",i1+1);
scanf("%d",&w);
i=LocateVex(G,v1);
j=LocateVex(G,v2);
s=(ArcNode *)malloc(sizeof(ArcNode));
s->adjvex=j;//弧所指的顶点的位置为j
s->weight=w;
s->nextarc=G.vertices[i].firstarc;
G.vertices[i].firstarc=s;
}
}
//输出邻接表
void printAdjList(ALGraph G)
{
int i;
ArcNode *p;
printf("%4s%6s%12s\n","编号","顶点","相邻边编号");
for(i=0;i<G.vexnum;i++)
{
printf("%4d%5c",i,G.vertices[i].data);
for(p=G.vertices[i].firstarc;p;p=p->nextarc)
printf("%3d",p->adjvex);//弧所指的顶点的位置
printf("\n");
}
}
//对顶点求入度,需要遍历邻接矩阵
void FindInDegree(ALGraph G,int *indegree)
{
ArcNode *s;
for(int i=0;i<G.vexnum;i++)
{
s=G.vertices[i].firstarc;
while(s)
{
indegree[s->adjvex]++;
s=s->nextarc;
}
}
}
//拓扑排序
int ve[MAX_VERTEX_NUM];
int TopologicalOrder(ALGraph G,SqStack &T)
{
SqStack S;
int i,k,count,*indegree;
ArcNode *P;
indegree=(int *)malloc(G.vexnum*sizeof(int));//顶点入度数组
for(i=0;i<G.vexnum;i++)
indegree[i]=0;
FindInDegree(G,indegree);//求各点入度
InitStack(S);
InitStack(T);//初始化栈
for(i=0;i<G.vexnum;i++)
if(!indegree[i])Push(S,i);
count=0;
for(i=0;i<G.vexnum;i++)
ve[i]=0;
while(!StackEmpty(S))
{
Pop(S,&i);//拿出入度为0的顶点
Push(T,i);
++count;
ArcNode *p;
for(p=G.vertices[i].firstarc;p;p=p->nextarc)
{
k=p->adjvex;
if(!(--indegree[k]))
Push(S,k);
if(ve[i]+p->weight>ve[k])
ve[k]=ve[i]+p->weight;
}
}
if(count<G.vexnum)
return 0;
else
return 1;
}
//图G为有向图,输出G中的关键活动
int CriticalPath(ALGraph G)
{
int v1[MAX_VERTEX_NUM];
SqStack T;
int i,j,k,dut,ee,e1;
char tag;
ArcNode *p;
if(!TopologicalOrder(G,T))
return 0;
for(i=0;i<G.vexnum;i++)
v1[i]=ve[G.vexnum-1];//初始化顶点事件的最迟发生时间
while(!StackEmpty(T))//按拓扑排序逆序求各个顶点的v1值
for(Pop(T,&j),p=G.vertices[j].firstarc;p;p=p->nextarc)
{
k=p->adjvex;
dut=p->weight;
if(v1[k]-dut<v1[j])
v1[j]=v1[k]-dut;
}
printf("(vi,vj)dut ee e1(*)\n");
for(j=0;j<G.vexnum;j++)//求ee,e1和关键活动
for(p=G.vertices[j].firstarc;p;p=p->nextarc)
{
k=p->adjvex;
dut=p->weight;
ee=ve[j];
e1=v1[k]-dut;
tag=(ee==e1)? '*':' ';
printf("(%c,%c)%d %d %d %c\n",G.vertices[j].data,G.vertices[k].data,dut,ee,e1,tag);
}
printf("顶点i ve(i) v1(i)\n");
for(j=0;j<G.vexnum;j++)
printf("%5c%5d%5d\n",G.vertices[j].data,ve[j],v1[j]);
return 1;
}
int main()
{
ALGraph G;
creatDN(G);//构造图的邻接表
printAdjList(G);//输出邻接表
printf("标*的活动为图G关键路径上的活动\n");
CriticalPath(G);//求图G的关键路径
}
#include<stdlib.h>
#define MAX_VERTEX_NUM 20//顶点最大个数
typedef int Status;//函数的类型,其值是函数结果状态代码
typedef char VertexType;//顶点元素的类型
typedef int ElemType;
typedef struct ArcNode
{
int adjvex;//该弧所指的顶点的位置
struct ArcNode *nextarc;//指向下一条狐的指针
int weight;//边的权
}ArcNode;//表的结点
typedef struct Vnode
{
VertexType data;
ArcNode *firstarc;
}VNode,AdjList[MAX_VERTEX_NUM];
typedef struct
{
AdjList vertices;
int vexnum,arcnum;
int kind;//图的种类
}ALGraph;
typedef struct SqStack
{
ElemType elem[MAX_VERTEX_NUM];
int top;
}SqStack;
//初始化栈
void InitStack(SqStack &S)
{
S.top=-1;
}
//判断栈空否,1为空
Status StackEmpty(SqStack S)
{
if(S.top==-1)
return 1;
else
return 0;
}
//入栈
Status Push(SqStack &S,ElemType e)
{
if(S.top==MAX_VERTEX_NUM-1)
return 0;
S.elem[++S.top]=e;
return 1;
}
//栈顶元素出栈
Status Pop(SqStack &S,ElemType *e)
{
if(S.top==-1)
return 0;
*e=S.elem[S.top--];
return 1;
}
//返回顶点v在图顶点向量中的位置
int LocateVex(ALGraph G,char v)
{
int i;
for(int i=0;v!=G.vertices[i].data&&i<G.vexnum;++i);
if(i>=G.vexnum)
return -1;
return i;
}
//建立邻接表
void creatDN(ALGraph &G)
{
int i,j,w;
char v1,v2;
ArcNode *s;
printf("输入图的顶点数:");
scanf("%d",&G.vexnum);
printf("输入图的边数:");
scanf("%d",&G.arcnum);
for(i=0;i<G.vexnum;i++)
{
printf("输入第%d的顶点的信息:",i+1);
scanf("%s",&G.vertices[i].data);
G.vertices[i].firstarc=NULL;
}
for(int i1=0;i1<G.arcnum;i1++)//该弧所指的顶点的位置
{
printf("输入第%d个活动的先序顶点:",i1+1);
scanf("%s",&v1);
printf("输入第%d个活动的后序顶点:",i1+1);
scanf("%s",&v2);
printf("输入这个活动的时间:",i1+1);
scanf("%d",&w);
i=LocateVex(G,v1);
j=LocateVex(G,v2);
s=(ArcNode *)malloc(sizeof(ArcNode));
s->adjvex=j;//弧所指的顶点的位置为j
s->weight=w;
s->nextarc=G.vertices[i].firstarc;
G.vertices[i].firstarc=s;
}
}
//输出邻接表
void printAdjList(ALGraph G)
{
int i;
ArcNode *p;
printf("%4s%6s%12s\n","编号","顶点","相邻边编号");
for(i=0;i<G.vexnum;i++)
{
printf("%4d%5c",i,G.vertices[i].data);
for(p=G.vertices[i].firstarc;p;p=p->nextarc)
printf("%3d",p->adjvex);//弧所指的顶点的位置
printf("\n");
}
}
//对顶点求入度,需要遍历邻接矩阵
void FindInDegree(ALGraph G,int *indegree)
{
ArcNode *s;
for(int i=0;i<G.vexnum;i++)
{
s=G.vertices[i].firstarc;
while(s)
{
indegree[s->adjvex]++;
s=s->nextarc;
}
}
}
//拓扑排序
int ve[MAX_VERTEX_NUM];
int TopologicalOrder(ALGraph G,SqStack &T)
{
SqStack S;
int i,k,count,*indegree;
ArcNode *P;
indegree=(int *)malloc(G.vexnum*sizeof(int));//顶点入度数组
for(i=0;i<G.vexnum;i++)
indegree[i]=0;
FindInDegree(G,indegree);//求各点入度
InitStack(S);
InitStack(T);//初始化栈
for(i=0;i<G.vexnum;i++)
if(!indegree[i])Push(S,i);
count=0;
for(i=0;i<G.vexnum;i++)
ve[i]=0;
while(!StackEmpty(S))
{
Pop(S,&i);//拿出入度为0的顶点
Push(T,i);
++count;
ArcNode *p;
for(p=G.vertices[i].firstarc;p;p=p->nextarc)
{
k=p->adjvex;
if(!(--indegree[k]))
Push(S,k);
if(ve[i]+p->weight>ve[k])
ve[k]=ve[i]+p->weight;
}
}
if(count<G.vexnum)
return 0;
else
return 1;
}
//图G为有向图,输出G中的关键活动
int CriticalPath(ALGraph G)
{
int v1[MAX_VERTEX_NUM];
SqStack T;
int i,j,k,dut,ee,e1;
char tag;
ArcNode *p;
if(!TopologicalOrder(G,T))
return 0;
for(i=0;i<G.vexnum;i++)
v1[i]=ve[G.vexnum-1];//初始化顶点事件的最迟发生时间
while(!StackEmpty(T))//按拓扑排序逆序求各个顶点的v1值
for(Pop(T,&j),p=G.vertices[j].firstarc;p;p=p->nextarc)
{
k=p->adjvex;
dut=p->weight;
if(v1[k]-dut<v1[j])
v1[j]=v1[k]-dut;
}
printf("(vi,vj)dut ee e1(*)\n");
for(j=0;j<G.vexnum;j++)//求ee,e1和关键活动
for(p=G.vertices[j].firstarc;p;p=p->nextarc)
{
k=p->adjvex;
dut=p->weight;
ee=ve[j];
e1=v1[k]-dut;
tag=(ee==e1)? '*':' ';
printf("(%c,%c)%d %d %d %c\n",G.vertices[j].data,G.vertices[k].data,dut,ee,e1,tag);
}
printf("顶点i ve(i) v1(i)\n");
for(j=0;j<G.vexnum;j++)
printf("%5c%5d%5d\n",G.vertices[j].data,ve[j],v1[j]);
return 1;
}
int main()
{
ALGraph G;
creatDN(G);//构造图的邻接表
printAdjList(G);//输出邻接表
printf("标*的活动为图G关键路径上的活动\n");
CriticalPath(G);//求图G的关键路径
}