PTA How Long Does It Take 思路分析及代码解析

2024-03-29 14:32

本文主要是介绍PTA How Long Does It Take 思路分析及代码解析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

PTA How Long Does It Take 思路分析及代码解析v0.9.1

  • 一、前导
    • 1. 需要掌握的知识
    • 2. 题目信息
  • 二、解题思路分析
    • 1. 题意理解
      • 1. 1 输入数据
      • 1.2 输出数据
    • 2. 思路分析(重点)
  • 三、具体实现
    • 1. 弯路和bug
    • 2. 代码框架(重点)
      • 2.1 采用的数据结构
      • 2.2 程序主体框架
      • 2.3 各分支函数
    • 3. 完整AC编码
  • 四、参考

一、前导

1. 需要掌握的知识

  1. AOV网:顶点表示活动,边表示活动间先后关系的有向图 称做 顶点活动网络(Activity On Vertex network),简称AOV网
  2. 在AOV网中,若不存在回路,则所有活动可排列成一个线性序列,使得每个活动的所有前驱活动都排在该活动的前面,我们把此序列 称为 拓扑序列(Topological order),由AOV网构造拓扑序列的过程叫做 拓扑排序(Topological sort)。
  3. AOV网的拓扑序列不是唯一的,满足上述定义的任一线性序列都称作它的拓扑序列。
  4. AOV网构造出拓扑序列的实际意义:如果按照拓扑序列中的顶点次序,在开始每一项活动时,能够保证它的所有前驱活动都已完成,从而使整个工程顺序进行,不会出现冲突的情况。示例:某专业学生的排课
  5. 拓扑排序算法主要是循环执行以下两步,直到不存在入度为0的顶点为止
    (1) 选择一个入度为0的顶点并输出
    (2) 从AOV网中删除此顶点及所有出边
    循环结束后,若输出的顶点数 < AOV网中的顶点数,则说明图中存在回路,不存在拓扑序列;若相等,输出的顶点序列就是一种拓扑序列

2. 题目信息

  1. 题目来源:PTA / 拼题A
  2. 题目地址:How Long Does It Take

二、解题思路分析

1. 题意理解

  1. 拓扑排序相关问题

1. 1 输入数据

9 12  //图的顶点数和边数,顶点数最大值100,顶点从0开始编号
0 1 6 //边的两个顶点及其权重, 有向图 0-->1
0 2 4
...
7 8 4

1.2 输出数据

  1. 打印最早完成时间;图如果存在回路,打印 ‘Impossible’

2. 思路分析(重点)

  1. 拓扑排序相关问题:判断图中是否存在回路 + 计算出最早完成时间(不严谨的表述就是:边的权值之和的最大值)

三、具体实现

1. 弯路和bug

  1. 使用指针变量时,先申请内存空间,然后再使用
ptrAdjNode N;
N=(ptrAdjNode)malloc(sizeof(struct AdjNodeStructure));

2. 代码框架(重点)

2.1 采用的数据结构

  1. 使用邻接表存储图:图结构如下所示
typedef int vertex;
typedef int wightType;
#define max 100struct EdgeStruc  //边结构
{vertex V1;vertex V2;wightType weight;
};
typedef struct EdgeStruc *ptrEdge; typedef struct AdjNodeStructure *ptrAdjNode;
struct AdjNodeStructure //图顶点的邻接点
{vertex vertexIndex;wightType weight;ptrAdjNode next;
};struct HeadNode //邻接表的头结点
{ptrAdjNode AdjNode;
};
typedef struct HeadNode HeadNodeArray[max];struct GraphStructure //图
{int vertexNumber;int edgeNumber;HeadNodeArray head;
};
typedef struct GraphStructure *ptrGraph;

2.2 程序主体框架

               程序伪码描述
int main()
{	构建图 然后执行拓扑排序即可return 0;
}

2.3 各分支函数

  1. TopSort( ):拓扑排序子函数。拓扑排序算法主要是循环执行以下两步,直到不存在入度为0的顶点为止
    (1) 选择一个入度为0的顶点并输出
    (2) 从AOV网中删除此顶点及所有出边
    循环结束后,若输出的顶点数 < AOV网中的顶点数,则说明图中存在回路,不存在拓扑序列;若相等,输出的顶点序列就是一种拓扑序列
int TopSort()
{int Indegree[Graph->vertexNumber],cnt=0,front,result=0;vertex V;ptrAdjNode W;queue<vertex> q;/* 初始化入度 */for(V=0;V<Graph->vertexNumber;V++)Indegree[V]=0;/*遍历图 得到Indegree[] */for(V=0;V<Graph->vertexNumber;V++){W=Graph->head[V].AdjNode;while(W){Indegree[W->vertexIndex]++;W=W->next;}		} /*将所有入度为0的顶点入列*/for(V=0;V<Graph->vertexNumber;V++) {if(Indegree[V]==0){q.push(V);Earlist[V]=0;}}/*开始进行Top Sort*/while(!q.empty()) {front=q.front();q.pop();cnt++;//TopOrder[cnt++]=front;W=Graph->head[front].AdjNode; while(W) {if(Earlist[W->vertexIndex]<Earlist[front] + W->weight) //计算最早完成时间 Earlist[W->vertexIndex]=Earlist[front]+W->weight; if(--Indegree[W->vertexIndex] == 0){q.push(W->vertexIndex);}	W=W->next;	} }if(cnt!=Graph->vertexNumber)return result;else {  // Earlist数组中的最大值就是最早完成时间for(V=0;V<Graph->vertexNumber;V++)  {if(Earlist[V]>result)result=Earlist[V];}return result;} 
}
  1. BuildGraph( ) :通过邻接表存储图,属于建图的基础练习

3. 完整AC编码

  1. 本文如果对你有帮助,请点赞鼓励 ,谢谢 😊
  2. 如有建议或意见,欢迎留言
#include <queue>
#include <cstdlib>
#include <iostream>
using namespace std;typedef int vertex;
typedef int wightType;
#define max 100struct EdgeStruc
{vertex V1;vertex V2;wightType weight;
};
typedef struct EdgeStruc *ptrEdge; typedef struct AdjNodeStructure *ptrAdjNode;
struct AdjNodeStructure
{vertex vertexIndex;wightType weight;ptrAdjNode next;
};struct HeadNode
{ptrAdjNode AdjNode;
};
typedef struct HeadNode HeadNodeArray[max];struct GraphStructure
{int vertexNumber;int edgeNumber;HeadNodeArray head;
};
typedef struct GraphStructure *ptrGraph;ptrGraph Graph;
int Earlist[max]={0}; //统计最早完成时间 
//vertex TopOrder[max]; //存放拓扑排序的结果void CreateNullNodeGraph();
void BuildGraph();
void insertEdge(ptrEdge Edge);
int TopSort();int main()
{	int result;BuildGraph();result=TopSort();if(!result)cout<<"Impossible";elsecout<<result;return 0;
} int TopSort()
{int Indegree[Graph->vertexNumber],cnt=0,front,result=0;vertex V;ptrAdjNode W;queue<vertex> q;/* 初始化入度 */for(V=0;V<Graph->vertexNumber;V++)Indegree[V]=0;/*遍历图 得到Indegree[] */for(V=0;V<Graph->vertexNumber;V++){W=Graph->head[V].AdjNode;while(W){Indegree[W->vertexIndex]++;W=W->next;}		} /*将所有入度为0的顶点入列*/for(V=0;V<Graph->vertexNumber;V++) {if(Indegree[V]==0){q.push(V);Earlist[V]=0;}}/*开始进行Top Sort*/while(!q.empty()) {front=q.front();q.pop();cnt++;//TopOrder[cnt++]=front;W=Graph->head[front].AdjNode; while(W) {if(Earlist[W->vertexIndex]<Earlist[front] + W->weight) //计算最早完成时间 Earlist[W->vertexIndex]=Earlist[front]+W->weight; if(--Indegree[W->vertexIndex] == 0){q.push(W->vertexIndex);}	W=W->next;	} }if(cnt!=Graph->vertexNumber)return result;else {  // Earlist数组中的最大值就是最早完成时间for(V=0;V<Graph->vertexNumber;V++)  {if(Earlist[V]>result)result=Earlist[V];}return result;} 
}void CreateNullNodeGraph()
{Graph=(ptrGraph)malloc(sizeof(struct GraphStructure));cin>>Graph->vertexNumber>>Graph->edgeNumber;for(int i=0;i<Graph->vertexNumber;i++){Graph->head[i].AdjNode=NULL;}
}void BuildGraph()
{ptrEdge Edge;  CreateNullNodeGraph();for(int i=0;i<Graph->edgeNumber;i++){Edge=(ptrEdge)malloc(sizeof(struct EdgeStruc));cin>>Edge->V1>>Edge->V2>>Edge->weight;insertEdge(Edge);	}return;
}void insertEdge(ptrEdge Edge)
{ptrAdjNode N;N=(ptrAdjNode)malloc(sizeof(struct AdjNodeStructure));N->vertexIndex=Edge->V2;N->weight=Edge->weight;N->next=Graph->head[Edge->V1].AdjNode;Graph->head[Edge->V1].AdjNode=N;return;
}

四、参考

  1. 浙江大学 陈越、何钦铭老师主讲的数据结构

这篇关于PTA How Long Does It Take 思路分析及代码解析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/858841

相关文章

线上Java OOM问题定位与解决方案超详细解析

《线上JavaOOM问题定位与解决方案超详细解析》OOM是JVM抛出的错误,表示内存分配失败,:本文主要介绍线上JavaOOM问题定位与解决方案的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录一、OOM问题核心认知1.1 OOM定义与技术定位1.2 OOM常见类型及技术特征二、OOM问题定位工具

C#实现千万数据秒级导入的代码

《C#实现千万数据秒级导入的代码》在实际开发中excel导入很常见,现代社会中很容易遇到大数据处理业务,所以本文我就给大家分享一下千万数据秒级导入怎么实现,文中有详细的代码示例供大家参考,需要的朋友可... 目录前言一、数据存储二、处理逻辑优化前代码处理逻辑优化后的代码总结前言在实际开发中excel导入很

SpringBoot+RustFS 实现文件切片极速上传的实例代码

《SpringBoot+RustFS实现文件切片极速上传的实例代码》本文介绍利用SpringBoot和RustFS构建高性能文件切片上传系统,实现大文件秒传、断点续传和分片上传等功能,具有一定的参考... 目录一、为什么选择 RustFS + SpringBoot?二、环境准备与部署2.1 安装 RustF

Python实现Excel批量样式修改器(附完整代码)

《Python实现Excel批量样式修改器(附完整代码)》这篇文章主要为大家详细介绍了如何使用Python实现一个Excel批量样式修改器,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录前言功能特性核心功能界面特性系统要求安装说明使用指南基本操作流程高级功能技术实现核心技术栈关键函

深度解析Python中递归下降解析器的原理与实现

《深度解析Python中递归下降解析器的原理与实现》在编译器设计、配置文件处理和数据转换领域,递归下降解析器是最常用且最直观的解析技术,本文将详细介绍递归下降解析器的原理与实现,感兴趣的小伙伴可以跟随... 目录引言:解析器的核心价值一、递归下降解析器基础1.1 核心概念解析1.2 基本架构二、简单算术表达

深度解析Java @Serial 注解及常见错误案例

《深度解析Java@Serial注解及常见错误案例》Java14引入@Serial注解,用于编译时校验序列化成员,替代传统方式解决运行时错误,适用于Serializable类的方法/字段,需注意签... 目录Java @Serial 注解深度解析1. 注解本质2. 核心作用(1) 主要用途(2) 适用位置3

sky-take-out项目中Redis的使用示例详解

《sky-take-out项目中Redis的使用示例详解》SpringCache是Spring的缓存抽象层,通过注解简化缓存管理,支持Redis等提供者,适用于方法结果缓存、更新和删除操作,但无法实现... 目录Spring Cache主要特性核心注解1.@Cacheable2.@CachePut3.@Ca

Java MCP 的鉴权深度解析

《JavaMCP的鉴权深度解析》文章介绍JavaMCP鉴权的实现方式,指出客户端可通过queryString、header或env传递鉴权信息,服务器端支持工具单独鉴权、过滤器集中鉴权及启动时鉴权... 目录一、MCP Client 侧(负责传递,比较简单)(1)常见的 mcpServers json 配置

Redis实现高效内存管理的示例代码

《Redis实现高效内存管理的示例代码》Redis内存管理是其核心功能之一,为了高效地利用内存,Redis采用了多种技术和策略,如优化的数据结构、内存分配策略、内存回收、数据压缩等,下面就来详细的介绍... 目录1. 内存分配策略jemalloc 的使用2. 数据压缩和编码ziplist示例代码3. 优化的

从原理到实战解析Java Stream 的并行流性能优化

《从原理到实战解析JavaStream的并行流性能优化》本文给大家介绍JavaStream的并行流性能优化:从原理到实战的全攻略,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的... 目录一、并行流的核心原理与适用场景二、性能优化的核心策略1. 合理设置并行度:打破默认阈值2. 避免装箱