#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX_VERTEX_NUM 20
#define OVERFLOW 0
#define OK 1
#define TRUE 1
#define FALSE 0
#include<stack>
#define MAX 10000
using namespace std;
typedef int Status ;
typedef char VertexType;
typedef int QElemType;
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; //顶点数,边数
}ALGraph;
void CreateALGraph(ALGraph *G) //构建图
{
ArcNode *p;
int i,j,k,w;
printf("输入顶点与边的数目:\n");
scanf("%d%d",&G->vexnum,&G->arcnum);
getchar();
printf("输入顶点值:\n");
for(i=1;i<=G->vexnum;i++)
{
scanf("%c",&G->vertices[i].data);
getchar();
G->vertices[i].firstarc=NULL;
}
//建立边表
printf("输入邻接表对应的下标以及权值:\n");
for(k=1;k<=G->arcnum;k++)
{
scanf("%d%d%d",&i,&j,&w); //边对应的两个顶点下标并将俩顶点联系起来
p = (ArcNode *)malloc(sizeof(ArcNode));
p->adjvex = j;
p->weight = w;
p->nextarc = G->vertices[i].firstarc;
G->vertices[i].firstarc = p;
}
}
void FindIndgree(ALGraph G,int Indegree[MAX]){
memset(Indegree,0,sizeof(Indegree));
ArcNode *p;
for(int i = 1;i<=G.vexnum;i++){
p = G.vertices[i].firstarc;
while(p)
{
Indegree[p->adjvex]++;
p = p->nextarc;
}
}
}
int flag = 0; //全局变量为逆拓扑排序的各顶点置最长路径
/*先拓扑排好以及将对应的最长路径确定好*/
stack<int> T;
Status TopologicalSort(ALGraph G) //引入T栈,将s栈中的零入度元素依次压入,目的:寻找路径时先从s
//中最后入栈的开始,往前推判断是否为关键路径
{
stack<int> s;
ArcNode *p;
int count = 0;
int Indegree[MAX];
int ve[MAX]; //寻找路径的最长
FindIndgree(G,Indegree);
for(int i = 1;i<=G.vexnum;i++){
if(!Indegree[i]){
s.push(i);
}
}
for(int i = 1;i<=G.vexnum;i++) {
ve[i] = 0; //初始化
}
while(!s.empty()){
int item = s.top();
T.push(item);
s.pop();
count++;
for(p=G.vertices[item].firstarc;p;p=p->nextarc){
int k = p->adjvex;
if(!(--Indegree[k])) s.push(k); //入度为零,入栈
if(ve[item]+p->weight>ve[k]) ve[k] = ve[item]+p->weight; //如果前一个顶点(item)数组所含有的权值加上正在访问的p指向的权值相加
//与p的数组(k)所含的权值比较(向前推寻找最长路径)
}
}
flag = ve[G.vexnum];
if(count<G.vexnum) //有环退出
return false;
else
return OK;
}
void CriticalPath(ALGraph &G)
{
ArcNode *p;
if(!TopologicalSort(G)) exit(0) ;
int ve2[MAX] = {0};
for(int i = 1;i<=G.vexnum;i++){
ve2[i] = flag; //逆拓扑排序,将其各顶点元素赋最长路径
}
while(!T.empty()){
int k = T.top();
T.pop();
for(p = G.vertices[k].firstarc;p;p = p->nextarc){ //反向求各顶点数组的权值(寻求各顶点数组权值最小)
int j = p->adjvex;
int num = p->weight;
if(ve2[j]-num<ve2[k]) ve2[k] = ve2[j]-num;
}
// for(int i=1;i<=G.vexnum;i++)
// {
// for(p=G.vertices[i].firstarc;p;p=p->nextarc)
// {
// int t = p->adjvex;
// int ete = ve2[i];
// int lte = ve2[t]-p->weight;
// if(ete==lte) //如果符合TopologicalSort函数寻求最长路径确定的各个阶段则可输出该阶段的两顶点与对应的权值
// printf("%c->%c,length:%d\n",G.vertices[i].data,G.vertices[t].data,p->weight);
// }
// }
}
for(int i=1;i<=G.vexnum;)
{
for(p=G.vertices[i].firstarc;p;p=p->nextarc)
{
int t = p->adjvex;
int lte = ve2[t]-p->weight;
//printf("%d***%d***%d",lte,t,ve2[t]) ;
int ete = ve2[i];
if(ete==lte) //如果符合TopologicalSort函数寻求最长路径确定的各个阶段则可输出该阶段的两顶点与对应的权值
{
printf("%c->%c,length:%d\n",G.vertices[i].data,G.vertices[t].data,p->weight);
i = t; //如果此t顶点信息符合路径则直接跳到与这条t路径相关的路径上来探索。
}
}
}
}
int main(){
ALGraph G;
CreateALGraph(&G);
stack<int> T;
TopologicalSort(G);
printf("关键路径为:\n");
CriticalPath(G);
return 0;
}
图的关键路径
最新推荐文章于 2023-01-18 21:56:06 发布