浙大数据结构第八周之08-图8 How Long Does It Take

前置知识:

拓扑排序:

/* 邻接表存储 - 拓扑排序算法 */bool TopSort( LGraph Graph, Vertex TopOrder[] )
{ /* 对Graph进行拓扑排序,  TopOrder[]顺序存储排序后的顶点下标 */int Indegree[MaxVertexNum], cnt;Vertex V;PtrToAdjVNode W;Queue Q = CreateQueue( Graph->Nv );/* 初始化Indegree[] */for (V=0; V<Graph->Nv; V++)Indegree[V] = 0;/* 遍历图,得到Indegree[] */for (V=0; V<Graph->Nv; V++)for (W=Graph->G[V].FirstEdge; W; W=W->Next)Indegree[W->AdjV]++; /* 对有向边<V, W->AdjV>累计终点的入度 *//* 将所有入度为0的顶点入列 */for (V=0; V<Graph->Nv; V++)if ( Indegree[V]==0 )AddQ(Q, V);/* 下面进入拓扑排序 */ cnt = 0; while( !IsEmpty(Q) ){V = DeleteQ(Q); /* 弹出一个入度为0的顶点 */TopOrder[cnt++] = V; /* 将之存为结果序列的下一个元素 *//* 对V的每个邻接点W->AdjV */for ( W=Graph->G[V].FirstEdge; W; W=W->Next )if ( --Indegree[W->AdjV] == 0 )/* 若删除V使得W->AdjV入度为0 */AddQ(Q, W->AdjV); /* 则该顶点入列 */ } /* while结束*/if ( cnt != Graph->Nv )return false; /* 说明图中有回路, 返回不成功标志 */ elsereturn true;
}

题目详情:

Given the relations of all the activities of a project, you are supposed to find the earliest completion time of the project.

Input Specification:

Each input file contains one test case. Each case starts with a line containing two positive integers N (≤100), the number of activity check points (hence it is assumed that the check points are numbered from 0 to N−1), and M, the number of activities. Then M lines follow, each gives the description of an activity. For the i-th activity, three non-negative numbers are given: S[i]E[i], and L[i], where S[i] is the index of the starting check point, E[i] of the ending check point, and L[i] the lasting time of the activity. The numbers in a line are separated by a space.

Output Specification:

For each test case, if the scheduling is possible, print in a line its earliest completion time; or simply output "Impossible".

Sample Input 1:

9 12
0 1 6
0 2 4
0 3 5
1 4 1
2 4 1
3 5 2
5 4 0
4 6 9
4 7 7
5 7 4
6 8 2
7 8 4

Sample Output 1:

18

Sample Input 2:

4 5
0 1 1
0 2 2
2 1 3
1 3 4
3 2 5

Sample Output 2:

Impossible

简单翻译:

第i行实际上给出的是一条有向边的信息,包括这条边的起点,终点和权值,要求在对这些事件进行拓扑排序后找到完成这系列事件所需时间,暂未涉及到关键路径问题,不要想复杂

主要思路:

难点:

(一)如何建图

第i行实际上给出的是一条有向边的信息,包括这条边的起点,终点和权值

用邻接矩阵建图应该也可以,不过锻炼能力还是用邻接表建图

(二)如何遍历

拓扑排序

关键一:

Earliest的更新:Earliest[i]表示完成节点i所需的最早时间单位,但因为存在不同的依赖关系,所以在若干前置事件完成后必须从中挑出一个最大的

关键二:

不是vertexNums-1就是结束事件,而是要在Earliest数组中找到最大值

代码实现:

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#define MAX_NODE_NUMS 105
#define TRUE 1
#define FALSE 0
#define NONE -1
typedef int bool;
/*实现队列的数据结构*/
typedef struct QueueNode QueueNode;
typedef QueueNode* Queue;
struct QueueNode {int Head, Rear, Size;int Data[MAX_NODE_NUMS];
};
void InitQueue(Queue* q) {(*q)->Head = 0;(*q)->Rear = -1;(*q)->Size = 0;for(int i = 0; i < MAX_NODE_NUMS; i++) {(*q)->Data[i] = NONE;}
}
bool IsEmpty(Queue* q) {if((*q)->Size == 0) {return TRUE;}else {return FALSE;}
}
bool IsFull(Queue* q) {if((*q)->Size == MAX_NODE_NUMS) {return TRUE;}else {return FALSE;}
}
void Enqueue(Queue* q, int data) {if(!IsFull(q)) {(*q)->Data[((*q)->Rear + 1) % MAX_NODE_NUMS] = data;(*q)->Rear = ((*q)->Rear + 1) % MAX_NODE_NUMS;(*q)->Size++;return;}
}
int Dequeue(Queue* q) {if(!IsEmpty(q)) {int ret = (*q)->Data[(*q)->Head];(*q)->Head = ((*q)->Head + 1) % MAX_NODE_NUMS;(*q)->Size--;return ret;}
}
/*实现邻接表构造的图的数据结构*/ 
typedef struct EdgeNode EdgeNode;
typedef EdgeNode* PToEdge;
struct EdgeNode {int Start, End, Weight;
};
typedef struct AdjVNode AdjVNode;
typedef AdjVNode* PToAdjVNode;
struct AdjVNode {int Index;int Weight;PToAdjVNode Next;
};
typedef struct HeadNode HeadNode;
struct HeadNode {int Data;PToAdjVNode FirstEdge;
};
typedef struct ListGraphNode ListGraphNode;
typedef ListGraphNode* ListGraph;
struct ListGraphNode {int VertexNums, EdgeNums;HeadNode Head[MAX_NODE_NUMS];
};
ListGraph CreateEmptyGraph(int vertexNums) {ListGraph graph = (ListGraph)malloc(sizeof(ListGraphNode));graph->VertexNums = vertexNums;for(int i = 0; i < graph->VertexNums; i++) {graph->Head[i].FirstEdge = NULL;}return graph;
}
/*注意,这里插入的是有向边*/
void InsertEdge(PToEdge edge, ListGraph graph) {PToAdjVNode newNode = (PToAdjVNode)malloc(sizeof(AdjVNode));newNode->Index = edge->End;newNode->Weight = edge->Weight;newNode->Next = graph->Head[edge->Start].FirstEdge;graph->Head[edge->Start].FirstEdge = newNode;return;
}
ListGraph BuildGraph(int vertexNums, int edgeNums) {ListGraph graph = CreateEmptyGraph(vertexNums);graph->EdgeNums = edgeNums;for(int i = 0; i < edgeNums; i++) {PToEdge edge = (PToEdge)malloc(sizeof(EdgeNode));scanf("%d %d %d", &(edge->Start), &(edge->End), &(edge->Weight));InsertEdge(edge, graph);free(edge);}return graph;
}
int InDegree[MAX_NODE_NUMS];
int Earliest[MAX_NODE_NUMS];
void TopSort(ListGraph graph) {/*初始化*/for(int i = 0; i < graph->VertexNums; i++) {for(PToAdjVNode p = graph->Head[i].FirstEdge; p; p = p->Next) {InDegree[p->Index]++;}}Queue q = (Queue)malloc(sizeof(QueueNode));InitQueue(&q);int Vcount = 0;for(int i = 0; i < graph->VertexNums; i++) {if(InDegree[i] == 0) {Enqueue(&q, i);Earliest[i] = 0;}}   while(!IsEmpty(&q)) {int vertexIndex = Dequeue(&q);Vcount++;for(PToAdjVNode p = graph->Head[vertexIndex].FirstEdge; p; p = p->Next) {if(Earliest[p->Index] < Earliest[vertexIndex] + p->Weight) {Earliest[p->Index] = Earliest[vertexIndex] + p->Weight;}if(--InDegree[p->Index] == 0) {Enqueue(&q, p->Index);}}}if(Vcount != graph->VertexNums) {printf("Impossible");}else {int max = 0;for(int i = 0; i < graph->VertexNums; i++) {if(Earliest[i] > max) {max = Earliest[i];}}printf("%d", max);}
}
int main() {int vertexNums, edgeNums;scanf("%d %d", &vertexNums, &edgeNums);ListGraph graph = BuildGraph(vertexNums, edgeNums);TopSort(graph);system("pause");return 0;
}                                                                                                                   

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/47658.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络面试题(172.22.141.231/26,该IP位于哪个网段? 该网段拥有多少可用IP地址?广播地址是多少?)

此题面试中常被问到&#xff0c;一定要会172.22.141.231/26&#xff0c;该IP位于哪个网段&#xff1f; 该网段拥有多少可用IP地址&#xff1f;广播地址是多少&#xff1f; 解题思路&#xff1a; 网络地址&#xff1a;172.22.141.192 10101100.00010110.10001101.11000000 广播…

【后端速成 Vue】第一个 Vue 程序

1、为什么要学习 Vue&#xff1f; 为什么使用 Vue? 回想之前&#xff0c;前后端交互的时候&#xff0c;前端收到后端响应的数据&#xff0c;接着将数据渲染到页面上&#xff0c;之前使用的是 JavaScript 或者 基于 JavaScript 的 Jquery&#xff0c;但是这两个用起来还是不太…

uni-app 打包生成签名Sha1

Android平台打包发布apk应用&#xff0c;需要使用数字证书&#xff08;.keystore文件&#xff09;进行签名&#xff0c;用于表明开发者身份。 可以使用JRE环境中的keytool命令生成。以下是windows平台生成证书的方法&#xff1a; 安装JRE环境&#xff08;推荐使用JRE8环境&am…

yolov8模型转onnx模型 和 tensorRT 模型

转onnx模型 在 安装好 pip install onnxruntime-gpu pip install onnx onnxconverter-common 出现 No module named cpuinfo 错误&#xff0c;通过安装&#xff1a; pip install py-cpuinfo 解决该问题。 import sys # 即 ultralytics文件夹 所在绝对路径 sys.path.app…

STM32 GPIO复习

GPIO General Purpose Input Output&#xff0c;即通用输入输出端口&#xff0c;简称GPIO。 负责采集外部器件的信息或控制外部器件工作&#xff0c;即输入输出。 不同型号&#xff0c;IO口数量可能不一样&#xff0c;可通过选型手册快速查询。 能快速翻转&#xff0c;每次翻…

Crimson:高性能,高扩展的新一代 Ceph OSD

背景 随着物理硬件的不断发展&#xff0c;存储软件所使用的硬件的情况也一直在不断变化。 一方面&#xff0c;内存和 IO 技术一直在快速发展&#xff0c;硬件的性能在极速增加。在最初设计 Ceph 的时候&#xff0c;通常情况下&#xff0c;Ceph 都是被部署到机械硬盘上&#x…

vellum (Discovering Houdini VellumⅡ柔体系统)学习笔记

视频地址&#xff1a; https://www.bilibili.com/video/BV1ve411u7nE?p3&spm_id_frompageDriver&vd_source044ee2998086c02fedb124921a28c963&#xff08;搬运&#xff09; 个人笔记如有错误欢迎指正&#xff1b;希望可以节省你的学习时间 ~享受艺术 干杯&#x1f37b…

Vue——如何在安卓项目中加载离线vue项目

最近在做一个离线工单的功能&#xff0c;为了直接复用原来在线H5的代码&#xff0c;我希望将它放到安卓本地来加载&#xff0c;做法比较简单&#xff0c;无非就是npm run build打包&#xff0c;然后把包放到安卓项目的assets目录下&#xff0c;然后按照正常加载webview的方式加…

jira增删改查接口

安装 pip install atlassian-python-api3.40.1 若安装失败,可尝试加上清华源(-i https://pypi.tuna.tsinghua.edu.cn/simple) 使用 为了防止信息泄露&#xff0c;可将账号密码单独存放到json文件中 &#xff0c;如credential.json {"name" : "xiaoming"…

python常用

环境配置 conda Conda自动补全 在终端激活conda环境的时候按tab不能自动补全activate和环境名。安装后可用tab进行补全。 安装 conda-bash-completion 插件&#xff1a;GitHub 安装方法&#xff1a; conda install -c conda-forge conda-bash-completion常用命令 #创建虚拟…

通过几段代码,详解Python单线程、多线程、多进程

在使用爬虫爬取数据的时候&#xff0c;当需要爬取的数据量比较大&#xff0c;且急需很快获取到数据的时候&#xff0c;可以考虑将单线程的爬虫写成多线程的爬虫。下面来学习一些它的基础知识和代码编写方法。 一、进程和线程 进程可以理解为是正在运行的程序的实例。进程是拥…

Kubernetes 使用 Rancher 管理

K8S集群管理工具 只能管理单个K8S集群 kubectl命令行管理工具 dashboard&#xff08;K8S官方的UI界面图形化管理工具&#xff09; &#xff08;管理多集群很麻烦&#xff0c;切换不同集群每次需要更改kube-config文件[kubectl配置文件]&#xff0c;如果kubeadm部署每次都需…

C++ 类与对象关系、生成

C 类与对象关系、生成举例如下&#xff1a; #include <iostream>class student { public:int No;int Score; public:void setScore(int s) {Score s;}int getScore() {return Score;}void setNo(int n) {No n;}int getNo() {return No;} };int main(int argc, char *a…

bigemap如何批量添加地图?

bigemap如何批量添加地图&#xff1f; 说明&#xff1a;批量添加可以同时添加多个在线地图&#xff0c;一次性添加完成&#xff08;批量添加无法验证地址是否可以访问&#xff09;&#xff08;批量配置文件可以在官网获取&#xff09; 第一步选择地图点进去点(添加号) 第二步&…

常见前端基础面试题(HTML,CSS,JS)(七)

同源策略 浏览器有一个重要的安全策略&#xff0c;称之为同源策略 其中&#xff0c;协议、端口号、域名必须一致&#xff0c;&#xff0c;称之为同源&#xff0c;两个源不同&#xff0c;称之为跨源或跨域 同源策略是指&#xff0c;若页面的源和页面运行过程中加载的源不一致…

原生无限极目录树详细讲解

原生无限级目录树 当涉及到原生的无限级目录树&#xff0c;我们可以使用递归算法来实现。以下是一个使用 JavaScript 实现原生无限级目录树的示例 介绍 原生无限级目录树是一种常见的数据结构&#xff0c;用于组织多层级的目录或分类数据。通过递归算法&#xff0c;我们可以…

Unity框架学习--资源管理器

资源加载方案 1、Inspector窗口拖拽 在脚本中用public声明变量&#xff0c;然后在Inspector窗口把要加载的资源拖拽给该脚本的变量。 不建议在大型项目使用。在公司的项目也不要用。 如果你是独立游戏开发者&#xff0c;则可以用。 不支持热更…

Linux面试笔试题(5)

79、下列工具中可以直接连接mysql的工具有【c 】。 A.xhsell B.plsql C.navicat D.以上都不是 Navicat 是一套可创建多个连接的数据库开发工具&#xff0c; 让你从单一应用程序中同时连接 MySQL、Redis、MariaDB、MongoDB、 SQL Server、Oracle、PostgreSQL和 SQLite 。它与…

七夕给TA满分宠爱!浪漫攻略为约会加分

浪漫的七夕将至&#xff0c;无论是异地恋人还是约会情侣&#xff0c;怎么能缺少节日仪式感~精心策划的约会计划&#xff0c;让浪漫“超级加倍”。 美好的二人世界&#xff0c;共度甜蜜时光&#xff0c;当然需要提前做好攻略&#xff0c;风和日丽的好天气能为约会加分不少。在规…

ArcGIS Serve Windows下用户密码变更导致Server服务无法启动问题

问题&#xff1a; 因未知原因Windows下的Server安装账户密码变更&#xff0c;但是又忘记了密码&#xff0c;导致&#xff0c;Server服务启动失败&#xff0c;错误1069&#xff1a; 解决方法&#xff1a; 在账户管理界面&#xff0c;重置对应的arcgis账户的密码&#xff0c;…