关键路径问题--完美版
#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
{
? ? int adjvex; ? ?//該弧所指向的頂點的位置
? ? struct Arcnode *nextarc; ?//指向下一條弧的指針
? ? int weight;
} Arcnode; //儲弧的信息存
typedef struct
{
? ? Vertextype data; ? ?//頂點信息
? ? Arcnode *firstarc; ?//第一個表結點的地址,指向第一條依附該頂點的弧的指針
} Vnode,Adjlist[Maxvexnum]; //頭結點
typedef struct
{
? ? Adjlist vertexs;
? ? 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->adjvex = j;
? ? ? ? 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)
? ? ? ? {
? ? ? ? ? ? printf("%5s%5s%5d\n",G.vertexs[i].data,G.vertexs[p->adjvex].data,p->weight);
? ? ? ? ? ? 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)
? ? ? ? {
? ? ? ? ? ? indegree[p->adjvex]++;
? ? ? ? ? ? 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)
? ? ? ? {
? ? ? ? ? ? k = p->adjvex; //對i號頂點的每個鄰接點的入度減一
? ? ? ? ? ? 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)
? ? ? ? {
? ? ? ? ? ? k = p->adjvex;
? ? ? ? ? ? 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)
? ? ? ? {
? ? ? ? ? ? k = p->adjvex;
? ? ? ? ? ? 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;
}
轉載于:https://blog.51cto.com/5912119/1734724
總結
以上是生活随笔為你收集整理的关键路径问题--完美版的全部內容,希望文章能夠幫你解決所遇到的問題。