当前位置: 首页 > news >正文

08-图9 关键活动 (30 分)

1.题目

假定一个工程项目由一组子任务构成,子任务之间有的可以并行执行,有的必须在完成了其它一些子任务后才能执行。“任务调度”包括一组子任务、以及每个子任务可以执行所依赖的子任务集。

比如完成一个专业的所有课程学习和毕业设计可以看成一个本科生要完成的一项工程,各门课程可以看成是子任务。有些课程可以同时开设,比如英语和C程序设计,它们没有必须先修哪门的约束;有些课程则不可以同时开设,因为它们有先后的依赖关系,比如C程序设计和数据结构两门课,必须先学习前者。

但是需要注意的是,对一组子任务,并不是任意的任务调度都是一个可行的方案。比如方案中存在“子任务A依赖于子任务B,子任务B依赖于子任务C,子任务C又依赖于子任务A”,那么这三个任务哪个都不能先执行,这就是一个不可行的方案。

任务调度问题中,如果还给出了完成每个子任务需要的时间,则我们可以算出完成整个工程需要的最短时间。在这些子任务中,有些任务即使推迟几天完成,也不会影响全局的工期;但是有些任务必须准时完成,否则整个项目的工期就要因此延误,这种任务就叫“关键活动”。

请编写程序判定一个给定的工程项目的任务调度是否可行;如果该调度方案可行,则计算完成整个工程项目需要的最短时间,并输出所有的关键活动。

输入格式:

输入第1行给出两个正整数N(≤)和M,其中N是任务交接点(即衔接相互依赖的两个子任务的节点,例如:若任务2要在任务1完成后才开始,则两任务之间必有一个交接点)的数量。交接点按1~N编号,M是子任务的数量,依次编号为1~M。随后M行,每行给出了3个正整数,分别是该任务开始和完成涉及的交接点编号以及该任务所需的时间,整数间用空格分隔。

输出格式:

如果任务调度不可行,则输出0;否则第1行输出完成整个工程项目需要的时间,第2行开始输出所有关键活动,每个关键活动占一行,按格式“V->W”输出,其中V和W为该任务开始和完成涉及的交接点编号。关键活动输出的顺序规则是:任务开始的交接点编号小者优先,起点编号相同时,与输入时任务的顺序相反。

输入样例:

7 8
1 2 4
1 3 3
2 4 5
3 4 3
4 5 1
4 6 6
5 7 5
6 7 2

输出样例:

17
1->2
2->4
4->6
6->7

2.思路

-数据存储

输出格式:任务开始的交接点编号小者优先,起点编号相同时,与输入时任务的顺序相反

图用邻接表存储最合适,遍历时按照顶点和边顺序遍历,又因为邻接点插入时是后输入的插入到前面,所以满足后输入先输出的要求。

②需要额外用一个矩阵存储逆向的边

 

-主要思路

①拓扑排序统计出最快工期

②利用拓扑逆向排序(利用OutDegree数组和存储反向边的矩阵)算出每一个节点的最晚完成时间。

③计算没一条边的松弛时间并输出。

-关键函数

topSort && bottomSort

 

3.参考代码

#include <stdlib.h>
#include <cstdio>
#include <queue>
#define MaxVertexNum 102
#define INFINITY 65536
using namespace std;

typedef int Vertex;
typedef int WeightType;
typedef int DataType;

int Earliest[MaxVertexNum];
int Latest[MaxVertexNum];
int KeyEdge[MaxVertexNum][MaxVertexNum];


typedef struct ENode *Edge;
struct ENode{
    Vertex V1, V2;
    WeightType Weight;
};

typedef struct AdjVNode *PtrToAdjVNode;
struct AdjVNode{
    Vertex AdjV;
    WeightType Weight;
    PtrToAdjVNode Next;
    int flag;
};

typedef struct Vnode{
    PtrToAdjVNode FirstEdge;
    
} AdjList[MaxVertexNum];    /* AdjListÊÇÁÚ½Ó±íÀàÐÍ */


typedef struct GNode *LGraph;
struct GNode{
    int Nv;
    int Ne;
    AdjList G;
    WeightType Matrix[MaxVertexNum][MaxVertexNum];
};


LGraph CreateGraph( int VertexNum );
void InsertEdge( LGraph Graph, Edge E );
LGraph BuildGraph();

bool topSort(LGraph Graph);
int findEarliest(LGraph Graph);

void bottomSort(LGraph Graph, int EarilestTime);
void outPut(LGraph Graph, int DDL);


int main() {
    LGraph Graph = BuildGraph();
    
    if( !topSort(Graph) ) printf("0\n");
    else {
        int DDL = findEarliest(Graph);
        
        bottomSort(Graph, DDL);
        
        outPut(Graph, DDL);
    }
    
    
    
}


LGraph CreateGraph( int VertexNum )
{
    Vertex V, W;
    LGraph Graph;
    
    Graph = (LGraph)malloc( sizeof(struct GNode) );
    Graph->Nv = VertexNum;
    Graph->Ne = 0;
    
    for (V=0; V<Graph->Nv; V++)
        Graph->G[V].FirstEdge = NULL;
    
    for (V = 0; V<Graph->Nv; V++){
        for (W = 0; W<Graph->Nv; W++) {
            Graph->Matrix[V][W] = INFINITY;
            KeyEdge[V][W] = 1;
        }
    }
    return Graph;
}
void InsertEdge( LGraph Graph, Edge E )
{
    PtrToAdjVNode newNode = new AdjVNode;
    newNode->Weight = E->Weight;
    newNode->AdjV = E->V2;
    
    newNode->Next = Graph->G[E->V1].FirstEdge;
    Graph->G[E->V1].FirstEdge = newNode;
    
}
LGraph BuildGraph()
{
    LGraph Graph;
    int Nv;
    Edge E;
    Vertex V;
    
    scanf("%d", &Nv);
    Graph = CreateGraph(Nv);
    
    scanf("%d", &(Graph->Ne));
    
    if(Graph->Ne) {
        E = new ENode;
        for(int i=0; i<Graph->Ne; i++) {
            scanf("%d %d %d", &(E->V1), &(E->V2), &(E->Weight));
            E->V1--; E->V2--;
            Graph->Matrix[E->V2][E->V1] = E->Weight;
            InsertEdge(Graph, E);
        }
    }
    
    
    return Graph;
    
}

bool topSort(LGraph Graph)
{
    int cnt;
    int Indegree[MaxVertexNum];
    Vertex V;
    queue<Vertex> Q;
    
    cnt = 0;
    for( V=0; V<Graph->Nv; V++) {Indegree[V] = 0; Earliest[V] = 0; }
    
    for( V = 0; V < Graph->Nv; V++) {
        for(PtrToAdjVNode W = Graph->G[V].FirstEdge; W; W=W->Next) {
            Indegree[W->AdjV]++;
            
        }
    }
    for(V=0; V<Graph->Nv; V++) if(Indegree[V] == 0) Q.push(V);
    
    while(!Q.empty()) {
        V = Q.front();
        Q.pop();
        cnt++;
        
        for(PtrToAdjVNode W = Graph->G[V].FirstEdge; W; W=W->Next) {
            if(--Indegree[W->AdjV] == 0) Q.push(W->AdjV);
            if(Earliest[W->AdjV] < W->Weight + Earliest[V])
            {
                Earliest[W->AdjV] = W->Weight + Earliest[V];
                
            }
            
        }
        
        
    }
    
    if(cnt != Graph->Nv) return false;
    return true;
    
    
}
int findEarliest(LGraph Graph)
{
    
    Vertex V, MaxV;
    int compTime;
    compTime = Earliest[0];
    
    for(V = 1; V < Graph->Nv; V++) {
        if(Earliest[V] > compTime) {compTime = Earliest[V]; MaxV = V; }
    }
    
    return compTime;
    
    
    
}
void bottomSort(LGraph Graph, int earlyTime)
{
    int OutDegree2[MaxVertexNum];
    int cnt;
    Vertex V;
    queue<Vertex> Q;
    
    cnt = 0;
    
    for (V = 0; V < Graph->Nv; V++) {
        OutDegree2[V] = 0;
        Latest[V] = INFINITY;
    }
    
    for( V = 0; V < Graph->Nv; V++) {
        for(PtrToAdjVNode W = Graph->G[V].FirstEdge; W; W=W->Next) {
            OutDegree2[V]++;
        }
        if (!OutDegree2[V]) {
            Latest[V] = earlyTime;
        }
    }
    
    for(V=0; V<Graph->Nv; V++) if(OutDegree2[V] == 0) Q.push(V);
    
    while(!Q.empty()) {
        
        V = Q.front();
        Q.pop();
        cnt++;
       
        for (Vertex W = 0; W<Graph->Nv; W++) {
            
            if(Graph->Matrix[V][W] != INFINITY) {
                if (--OutDegree2[W] == 0) {
                    Q.push(W);
                }
                
                if (Latest[V] - Graph->Matrix[V][W] < Latest[W]) {
                    Latest[W] = Latest[V] - Graph->Matrix[V][W];
                }
                
            }
            
        }
        
        
        
    }
    for (Vertex V = 0; V<Graph->Nv; V++) {
        for (Vertex W = 0; W < Graph->Nv; W++) {
            KeyEdge[V][W] = Latest[W] - Earliest[V] - Graph->Matrix[W][V];
        }
    }
    
  
    
}
void outPut(LGraph Graph, int DDL)
{
    printf("%d\n", DDL);
    for (Vertex V = 0; V<Graph->Nv; V++) {
        for (PtrToAdjVNode W = Graph->G[V].FirstEdge; W; W=W->Next) {
            if (KeyEdge[V][W->AdjV] == 0) {
                printf("%d->%d\n", V+1, W->AdjV+1);
            }
        }
    }
}

 

 

 

 

转载于:https://www.cnblogs.com/acoccus/p/10786873.html

相关文章:

  • Numpy用户指南
  • 涨姿势:抛弃字母、数字和下划线写SHELL
  • c++实现扫描检测硬件改动
  • 百度地图API获取数据
  • leetcode 338. 比特位计数(Counting Bits)
  • 2019-04-30vmware虚拟机安装macos 10.8格式为iso
  • 【Python爬虫】听说你又闹书荒了?豆瓣读书9.0分书籍陪你过五一
  • Player Settings-Web
  • c++11多线程笔记
  • 微软UWP应用,导航栏设计。
  • Python 之继承
  • 写给我即将出生小孩的第一封信
  • Centos6.5安装Redis3.2.8
  • SSH connect issue 'exec request failed on channel 0'
  • SQL0668N Operation not allowed for reason code 3 on table TEST. SQLSTATE=57016
  • 收藏网友的 源程序下载网
  • 【EOS】Cleos基础
  • ES6, React, Redux, Webpack写的一个爬 GitHub 的网页
  • ES6系列(二)变量的解构赋值
  • java第三方包学习之lombok
  • PHP 程序员也能做的 Java 开发 30分钟使用 netty 轻松打造一个高性能 websocket 服务...
  • 从零搭建Koa2 Server
  • 回流、重绘及其优化
  • 基于OpenResty的Lua Web框架lor0.0.2预览版发布
  • 码农张的Bug人生 - 初来乍到
  • 入门级的git使用指北
  • 腾讯视频格式如何转换成mp4 将下载的qlv文件转换成mp4的方法
  • 网页视频流m3u8/ts视频下载
  • 为什么要用IPython/Jupyter?
  • 【运维趟坑回忆录 开篇】初入初创, 一脸懵
  • CMake 入门1/5:基于阿里云 ECS搭建体验环境
  • 好程序员大数据教程Hadoop全分布安装(非HA)
  • ​LeetCode解法汇总2583. 二叉树中的第 K 大层和
  • ​软考-高级-系统架构设计师教程(清华第2版)【第12章 信息系统架构设计理论与实践(P420~465)-思维导图】​
  • ​用户画像从0到100的构建思路
  • #DBA杂记1
  • #我与Java虚拟机的故事#连载10: 如何在阿里、腾讯、百度、及字节跳动等公司面试中脱颖而出...
  • $L^p$ 调和函数恒为零
  • (1)SpringCloud 整合Python
  • (10)工业界推荐系统-小红书推荐场景及内部实践【排序模型的特征】
  • (LeetCode C++)盛最多水的容器
  • (附源码)基于SpringBoot和Vue的厨到家服务平台的设计与实现 毕业设计 063133
  • ***利用Ms05002溢出找“肉鸡
  • ***原理与防范
  • .net core 6 使用注解自动注入实例,无需构造注入 autowrite4net
  • .NET Core 和 .NET Framework 中的 MEF2
  • .Net CoreRabbitMQ消息存储可靠机制
  • .NET MAUI学习笔记——2.构建第一个程序_初级篇
  • .NET Project Open Day(2011.11.13)
  • .Net 知识杂记
  • .net反编译工具
  • .vollhavhelp-V-XXXXXXXX勒索病毒的最新威胁:如何恢复您的数据?
  • /usr/bin/python: can't decompress data; zlib not available 的异常处理
  • @Pointcut 使用
  • @德人合科技——天锐绿盾 | 图纸加密软件有哪些功能呢?