#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#define Maxv 50

#define Maxvexnum 100

#define TRUE 1

#define FALSE 0

#define OK 1

#define ERROR 0

#define OVERFLOW -2

#define Sinitsize 100  //栈存储空间初始分配

#define Sincrement 50 //栈存储空间分配增

int ve[Maxvexnum];//存放最早发生时间

typedef char Vertextype[Maxv]; //顶点向量

typedef int  Selemtype;

typedef int  Status;

/*

www.quzhuanpan.comp

*/

typedef struct Arcnode

{

struct Arcnode *nextarc;  //指向下一条弧的指针

int weight;

} Arcnode; //储弧的信息存

typedef struct

{

Vertextype data;    //顶点信息

Arcnode *firstarc;  //第一个表结点的地址，指向第一条依附该顶点的弧的指针

typedef struct

{

int vexnum,arcnum;

} Algraph;

/*

www.quzhuanpan.comp

*/

typedef struct

{

Selemtype *base;

Selemtype *top;

int stacksize;

} Sqstack;

int Locatevex(Algraph &G,Vertextype u)//字符型的u

{

int i;

for(i = 0; i < G.vexnum; ++i)

if(strcmp(u,G.vertexs[i].data) == 0)

return i;

return OK;

}//all right

/*Status Listinsert(Algraph &G,int i,Arcnode *e) //在不带头结点的单链表L中第i个位置之前插入元素e

{

e->nextarc =&L;

L =*e;

return OK;

}*/

int Creategraph(Algraph &G)

{

int i,j,k,w;

Vertextype V1,V2;

Arcnode *e;

printf("请输入图的顶点数，边数(以空格作为间隔):\n");

scanf("%d%d",&G.vexnum,&G.arcnum);

printf("请输入%d个顶点的值(小于%d个字符):\n",G.vexnum,Maxv);

for(i = 0; i<G.vexnum; ++i) //构造顶点向量并初始化

{

scanf("%s",G.vertexs[i].data);

G.vertexs[i].firstarc = NULL;

}

printf("请输入%d条弧的弧尾，弧头和权值(以空格作为间隔):\n",G.arcnum);

for(k = 0; k < G.arcnum; ++k)

{

scanf("%s%s%d",V1,V2,&w);

i = Locatevex(G,V1);

j = Locatevex(G,V2);

e = (Arcnode *)malloc(sizeof(Arcnode)); //：为每条弧分配内存，插入链表

e->weight = w;

e->nextarc = NULL;

//Listinsert(G.vertexs[i].firstarc,1,&e);

e->nextarc=G.vertexs[i].firstarc;

G.vertexs[i].firstarc=e;

}

return OK;

}

/*

www.quzhuanpan.comp

*/

int Display(Algraph &G)

{

int i;

Arcnode *p;

printf("\n\n");

printf("%d个顶点:",G.vexnum);

for(i = 0; i < G.vexnum; ++i)

{

printf("%s  ",G.vertexs[i].data);

}

printf("\n\n\n");

printf("%d条弧:\n",G.arcnum);

for(i = 0; i < G.vexnum; ++i)

{

p = G.vertexs[i].firstarc;

while(p)

{

p = p->nextarc;

}

}

return OK;

}

void Findindegree(Algraph &G,int indegree[])

{

int i;

Arcnode *p;

for(i = 0; i < G.vexnum; ++i)

indegree[i] = 0;

for(i = 0; i < G.vexnum; ++i)

{

p = G.vertexs[i].firstarc;

while(p)

{

p = p->nextarc;

}

}

}

void Initstack(Sqstack &S)

{

S.base = (Selemtype *)malloc(Sinitsize * sizeof (Selemtype));

if(!(S.base))

exit(OVERFLOW);

S.top = S.base;

S.stacksize = Sinitsize;

}

Status Stackempty(Sqstack &S)

{

if(S.top == S.base)

return TRUE;

else return ERROR;

}

void Push(Sqstack &S,int &e)

{

if(S.top -S.base >= S.stacksize)

{

S.base = (Selemtype *)realloc(S.base,(S.stacksize + Sincrement) * sizeof(Selemtype));

if(!(S.base))

exit(OVERFLOW);

S.top = S.base + S.stacksize;

S.stacksize += Sincrement;

}

*(S.top)++ = e;

}

Status Pop(Sqstack &S,int &e)

{

if(S.top == S.base)

return ERROR;

e = *(--S.top);

return OK;

}

Status TopologicalOrder(Algraph &G, Sqstack &T)

{

int count1=0;

int count2=0;

int i,k,N=0;

int indegree[Maxvexnum];

Sqstack S;

Arcnode *p;

Findindegree(G,indegree);

Initstack(S);

for(i = 0; i < G.vexnum; ++i)

{

if(indegree[i]==0)

{

Push(S,i); //入度为零者进栈

count1++;

}

if(G.vertexs[i].firstarc==NULL)

N++;

}

if(count1>1)

{

printf("图中有%d个源点,不能找出关键路径!!!\n",count1);

return 0;

}

else  if(N>1)

{

printf("图中有%d个汇点,不能找出关键路径!!!\n",N);

return 0;

}//一个活动只有一个开始和一个结尾，故源点和汇点只可是一

printf("\n");

printf("拓扑序列:");

Initstack(T);

for(i = 0; i < G.vexnum; ++i)

ve[i] = 0;

while(!Stackempty(S))

{

Pop(S,i);

printf("%s ",G.vertexs[i].data);

Push(T,i);

++count2; //对输出顶点计数

for(p = G.vertexs[i].firstarc; p; p = p->nextarc)

{

if(--indegree[k] == 0)

Push(S,k);

if(ve[i] + p->weight > ve[k])

ve[k] = ve[i] + p->weight;

}

}

printf("\n\n");

if(count2 < G.vexnum)

{

printf("此有向网有回路\n");

return 0;

}

else return 1;

}

Status CriticalPath(Algraph &G)

{

int vl[Maxvexnum];

Sqstack T;

int i,j,k,ee,el,dut;

Arcnode *p;

if(!TopologicalOrder(G,T))

return 0;//如果返回不是1，后面的不执行

j= ve[0];

for(i = 0; i < G.vexnum; i++)

if(ve[i] > j)

j = ve[i];//终点的活动对应的最早发生时间

for(i = 0; i < G.vexnum; i++)

vl[i] = j;//全部赋值成终点的活动对应的最早发生时间

while(!Stackempty(T))

{

for(Pop(T,j),p = G.vertexs[j].firstarc; p ; p = p->nextarc)

{

dut = p->weight;

if(vl[k] - dut < vl[j])

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

}//栈T里面放的是逆拓扑序列,即放了对应的下标

}

printf("V  ve[i]  vl[i]\n");

for(i = 0; i < G.vexnum; ++i)

{

printf("%s  %d  %5d",G.vertexs[i].data,ve[i],vl[i]);

if(ve[i] == vl[i])

printf("  关键路径经过的顶点");

printf("\n");

}

printf("\n");

printf("注释：V为事件，ve[i]为最早开始时间，vl[i]为最迟开始时间。\n");

printf("\n");

printf("j----k----权值----ee----el\n");

for(j = 0; j < G.vexnum; ++j) //求ee,el和关键活动

for(p = G.vertexs[j].firstarc; p ; p = p->nextarc)

{

dut = p->weight;

ee = ve[j];

el = vl[k] - dut;

printf("%s-->%s  %3d  %5d  %5d  ",G.vertexs[j].data,G.vertexs[k].data,dut,ee,el);

if(ee == el)

printf("关键活动");

printf("\n");

}//for

printf("\n注释：ee为活动的最早开始时间，el为活动的最迟开始时间。");

j--;

printf("\n\n");

printf("完成整项工程需要时间为:%d",ve[j]);

printf("\n");

return OK;

}

/*

www.quzhuanpan.comp

*/

int main()

{

system("color 5f");

Algraph h;

Creategraph(h);

Display(h);

CriticalPath(h);

return 0;

}