关键路径(C语言 邻接表)
来源:互联网 发布:线切割报价软件 编辑:程序博客网 时间:2024/06/05 17:27
综述
一共四步
1、根据拓扑排序求ve
2、根据逆拓扑排序求vl
3、由ve求e,由vl求l
4、输出关键活动、权值
***************************************************************************************************************************
其中:
顶点对应事件发生,最早ve,最晚用vl
边对应活动开始,最早用e,最晚用l
求法
1、ve:ve[i] = max{ve[前]+边权}
ve[0]=0
2、vl:vl[i] = min{vl[后]-边权}
vl[最后]=ve[最后]
3、e:ve[前]
4、l:vl[后]-边权
***************************************************************************************************************************
关键路径
若额e[i] == l[i],则为关键活动
数据结构
//增加id用于标识边,与e和l数组下标对应//增加data记录边权值typedef struct Side//边{ int toVertex;//边指向的点 int data; int id; struct side *next;}Side,*sLink;typedef struct Vertex//顶点{ int data; sLink first;//第一个边}Vertex,AdjList[20];typedef struct Graph//图{ AdjList adj;//顶点数组,注意不是指针,用.不用-> int n,v;//顶点数,边数}Graph,*gLink;
创建
//新增边的权值与idvoid createGraph(gLink g){ int n,v,data; printf("请输入顶点数与边数"); scanf("%d %d",&n,&v); g->n = n; g->v = v; int i; for(i=0;i<n;i++) { printf("请输入顶点%d权值",i); scanf("%d",&data); g->adj[i].data = data; g->adj[i].first = NULL; } printf("请输入边信息"); int v1,v2,da; for(i=0;i<v;i++) { scanf("%d %d %d",&v1,&v2,&da); sLink s = (sLink)malloc(sizeof(Side)); s->toVertex = v2; s->next = g->adj[v1].first; g->adj[v1].first = s; s->data = da; s->id = i; }}
入度
void inDegree(gLink g,int *a){ int i; for(i=0;i<g->n;i++) { a[i]=0; } for(i=0;i<g->n;i++) { sLink s = g->adj[i].first; while(s) { a[s->toVertex]++; s = s->next; } }}
全局变量
//全局变量int vers[15];//栈,装入拓扑排序,用于逆拓扑排序int top = -1;//栈指针//顶点-->事件发生:最早ve,最晚vl//边-->活动:最早e,最晚lint ve[15]={0},vl[15]={0},e[15]={0},l[15]={0};
拓扑排序求ve
//拓扑排序求vevoid tuopu(gLink g){ int queue[10]; int front=0, rear=0; int a[g->n]; inDegree(g,a); int i; for(i=0;i<g->n;i++) { if(!a[i]) { queue[rear++] = i; } } while(front!=rear) { int v = queue[front++]; vers[++top] = v;//进栈 sLink s = g->adj[v].first; while(s) { if(!--a[s->toVertex]) { queue[rear++] = s->toVertex; } if(ve[v]+s->data>ve[s->toVertex]) ve[s->toVertex] = ve[v]+s->data;//为每一个后继顶点赋值ve s = s->next; } }}
关键路径
//关键路径void path(gLink g){ //根据逆拓扑求vl int i; int v = vers[top--]; vl[v] = ve[v]; while(top!=-1) { v = vers[top--];//出栈 sLink s = g->adj[v].first; vl[v]=vl[s->toVertex]; while(s) { if(vl[s->toVertex]-s->data<vl[v]) vl[v] = vl[s->toVertex]-s->data;//为每一个前驱顶点赋值vl s = s->next; } } //求e和l //从顶点遍历,为每一个边确定e和l for(i=0;i<g->n;i++) { sLink s = g->adj[i].first; while(s) { e[s->id] = ve[i];//当前边e等于顶点ve l[s->id] = vl[s->toVertex] - s->data;//当前边l等于指向顶点vl减去边权值 s = s->next; } } //求关键路径 //输出关键活动和边的头顶点尾顶点 //e=l的边为关键活动 int j; for(i=0;i<g->v;i++) { if(l[i]==e[i]) { printf("a%-5d",i); //遍历图,找到id为这个的边 for(j=0;j<g->n;j++) { sLink s = g->adj[j].first; while(s) { if(s->id==i) { printf("v%d-->v%d",j,s->toVertex); break; } s=s->next; } } printf("\n"); } } //求总权值 //由于关键路径不一定只有一条 //所以从顶点开始,找到关键活动则跳到指向的下一个顶点,这样可以只得到一条关键路径 int quan = 0; sLink s = g->adj[0].first; while(s) { if(e[s->id]==l[s->id]) { quan += s->data; s = g->adj[s->toVertex].first; }else { s = s->next; } } printf("权值为:%d",quan);}
主函数
int main(){ gLink g = (gLink)malloc(sizeof(Graph)); createGraph(g); tuopu(g); path(g); return 0;}
阅读全文
1 0
- 关键路径(C语言 邻接表)
- 邻接表关键路径
- 关键路径_AOE_基于邻接表
- C语言关键路径实现
- C语言实现关键路径
- 关键路径 C语言实现
- 邻接表(c语言)
- C语言实现“关键路径”的求解
- 邻接表:C语言实现
- 将图读进邻接表实现文件C语言
- 反转一个邻接表C语言
- C语言里面邻接表的创建
- 复习(数据结构):图:c语言:邻接表
- C语言邻接表的实现
- 拓扑排序(C语言 邻接表)
- dijkstra算法(C语言 邻接表)
- floyd算法(C语言 邻接表)
- 数据结构之---C语言实现关键路径AOE图
- 本质
- Inno Setup入门实例教程 Inno Setup打包工具新手教程(图文)
- SDN
- Android Studio中Gradle的部分相关配置
- Linux-vi编辑器拷贝整行
- 关键路径(C语言 邻接表)
- IDEA使用技巧、快捷键一览表
- 有用的工具
- STM32定时器
- 使用JavaScript和MQTT开发物联网应用
- 计算机、c语言之进制浅析
- 计算机启动过程
- liunux 命令
- oracle11.2 在Centos7上安装