题目地址

https://pta.patest.cn/pta/test/15/exam/4/question/719

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

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

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

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

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

输入格式:

输入第1行给出两个正整数NN(\le 100≤100)和MM,其中NN是任务交接点(即衔接相互依赖的两个子任务的节点,例如:若任务2要在任务1完成后才开始,则两任务之间必有一个交接点)的数量。交接点按1~NN编号,MM是子任务的数量,依次编号为1~MM。随后MM行,每行给出了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
/*
该问题主体框架与上一题相似,也是拓扑排序,但是这次求关键路径。
不想用太繁琐的解法,想尽量照搬上一题的代码。
提出一个概念——松节点,与该节点相连的所有路径都【不是】关键路径。规则如下:
1 如果该结点【发出的所有边】,距离下个结点的开始时间都有富余,那么该节点是松节点。
2 若一个节点发出的所有边都连到了松节点上,那么该点也是松节点。
3 如果存在多个终点 该节点为终点,且结束时间比最晚的终点要早,那么该终点为松节点。
其中第三条最容易被忽略掉,导致始终不能AC,结果发现添了第三条还是不能AC
另,结果理论上正确,但是题目要求同一节点发出多条路径时,要按输入顺序逆序输出。
那么只好再加个计数了 评测结果
时间 结果 得分 题目 编译器 用时(ms) 内存(MB) 用户
2017-07-05 18:29 部分正确 26 5-11 gcc 2 1
测试点结果
测试点 结果 得分/满分 用时(ms) 内存(MB)
测试点1 答案正确 15/15 2 1
测试点2 答案正确 3/3 2 1
测试点3 答案正确 3/3 1 1
测试点4 答案正确 1/1 1 1
测试点5 答案正确 4/4 1 1
测试点6 答案错误 0/4 2 1 最后一个测试点拿不到成绩,然而手里没有数据能测出问题来
给的提示是【最大N,随机,可行】
然而并不清楚哪出了问题
先这么放着吧
*/
#include<stdio.h>
#define MAXN 120
#define TRUE 1
#define FALSE 0
#define ERROR -1
struct checkpoint{
int minStratTime;
int inEdgeCount;
int finished;
int loose;
}gCheckpointTable[MAXN]; int gMatrix[MAXN][MAXN];
int gCountInput[MAXN][MAXN]={0}; void InitCheckpointTable()
{
int i;
for(i=0;i<MAXN;i++)
{
gCheckpointTable[i].minStratTime=0;
gCheckpointTable[i].inEdgeCount=0;
gCheckpointTable[i].finished=0;
gCheckpointTable[i].loose=0;
}
}
void InitMatrix(N)
{
int i,j;
for(i=0;i<N;i++)
for(j=0;j<N;j++)
gMatrix[i][j]=ERROR;
} int FindPoint(N) //返回一个入度为0并且没被访问过的点
{
int i;
int p=ERROR;
for(i=0;i<N;i++)
{
if(gCheckpointTable[i].inEdgeCount==FALSE && gCheckpointTable[i].finished==FALSE)
p=i;
}
return p;
} void SetLoosePoint(int N,int maxtime) //找出所有的松节点,但是如果没有出边不能算松节点
{
int i,j;
int isLoose,count,countEdge,allLoose;
for(i=0;i<N;i++)
{
isLoose=TRUE;
count=0;
for(j=0;j<N;j++)
{
if(gMatrix[i][j]==ERROR)
continue;
count++;
if(gCheckpointTable[i].minStratTime+gMatrix[i][j]==gCheckpointTable[j].minStratTime)
isLoose=FALSE;
}
if(count!=0)
gCheckpointTable[i].loose=isLoose;
} do
{
count=0;
for(i=0;i<N;i++)
{
if(gCheckpointTable[i].loose==TRUE)
continue;
allLoose=TRUE;
countEdge=0;
for(j=0;j<N;j++)
{
if(gMatrix[i][j]==ERROR)
continue;
countEdge++;
if(gCheckpointTable[j].loose==FALSE)
{
allLoose=FALSE;
break;
}
}
if(allLoose==TRUE && countEdge!=0)
{
gCheckpointTable[i].loose=TRUE;
// printf("set %d loose\n",i+1);
count++;
}
if(countEdge==0 && gCheckpointTable[i].minStratTime<maxtime)
{
gCheckpointTable[i].loose=TRUE;
}
}
}
while(count);
} int PrintOredr(int N,int i)
{
int max,maxIDX,j;
maxIDX=ERROR;
max=0;
for(j=0;j<N;j++)
{
if(gCountInput[i][j]>max)
{
max=gCountInput[i][j];
maxIDX=j;
}
}
if(maxIDX != ERROR)
gCountInput[i][maxIDX]=0; return maxIDX;
}
void Calc(int N)
{
int i,j,maxtime,p;
while( (p=FindPoint(N)) != ERROR ) //如果还能返回入度为0的点 先叫它v1
{
gCheckpointTable[p].finished=TRUE; //先设为处理完成
for(i=0;i<N;i++)//遍历该点所有发出去的边,找一个连接到的点v2
{
if(gMatrix[p][i]==ERROR)
continue;
//如果被指向的结点v2,最小完成时间小于此节点v1的最小完成时间 加上 v1到v2的耗时,那么更新v2的最小时间
if(gCheckpointTable[i].minStratTime<gCheckpointTable[p].minStratTime+gMatrix[p][i])
gCheckpointTable[i].minStratTime = gCheckpointTable[p].minStratTime + gMatrix[p][i];
gCheckpointTable[i].inEdgeCount--; //将v2的入度减一
}
}
maxtime=0;
for(i=0;i<N;i++) //考虑到有多终点问题,算完后把所有节点全扫一遍,挑一个结束时间最大的打出来
{
if(gCheckpointTable[i].finished==FALSE)
{
printf("0");
return;
}
if(gCheckpointTable[i].minStratTime>maxtime)
maxtime=gCheckpointTable[i].minStratTime;
}
printf("%d\n",maxtime);
SetLoosePoint(N,maxtime);
for(i=0;i<N;i++)
{
while((j=PrintOredr(N,i))!=ERROR)
{
if(gCheckpointTable[i].loose==FALSE && gCheckpointTable[j].loose==FALSE && gMatrix[i][j]!=ERROR && gCheckpointTable[j].minStratTime==gCheckpointTable[i].minStratTime+gMatrix[i][j])
printf("%d->%d\n",i+1,j+1);
}
}
} int main()
{
int i;
int N,M;
int v1,v2,lastingTime,count;
scanf("%d %d",&N,&M);
InitMatrix(N);
InitCheckpointTable();
count=1;
for(i=0;i<M;i++)
{
scanf("%d %d %d",&v1,&v2,&lastingTime);
gMatrix[v1-1][v2-1]=lastingTime;
gCheckpointTable[v2-1].inEdgeCount++;
gCountInput[v1-1][v2-1]=count++;
}
Calc(N);
}

  

 

PTA 08-图9 关键活动 (30分)的更多相关文章

  1. PTA 7-2 哈夫曼编码 (30分)

    PTA 7-2 哈夫曼编码 (30分) 给定一段文字,如果我们统计出字母出现的频率,是可以根据哈夫曼算法给出一套编码,使得用此编码压缩原文可以得到最短的编码总长.然而哈夫曼编码并不是唯一的.例如对字符 ...

  2. PTA 11-散列4 Hard Version (30分)

    题目地址 https://pta.patest.cn/pta/test/16/exam/4/question/680 5-18 Hashing - Hard Version   (30分) Given ...

  3. PTA 04-树6 Complete Binary Search Tree (30分)

    题目地址 https://pta.patest.cn/pta/test/16/exam/4/question/669 5-7 Complete Binary Search Tree   (30分) A ...

  4. PTA 逆散列问题 (30 分)(贪心)

    题目链接:https://pintia.cn/problem-sets/1107178288721649664/problems/1107178432099737614 题目大意: 给定长度为 N 的 ...

  5. PTA 社交网络图中结点的“重要性”计算(30 分)

    7-12 社交网络图中结点的“重要性”计算(30 分) 在社交网络中,个人或单位(结点)之间通过某些关系(边)联系起来.他们受到这些关系的影响,这种影响可以理解为网络中相互连接的结点之间蔓延的一种相互 ...

  6. PTA数据结构与算法题目集(中文) 7-36 社交网络图中结点的“重要性”计算 (30 分)

    PTA数据结构与算法题目集(中文)  7-36 社交网络图中结点的“重要性”计算 (30 分) 7-36 社交网络图中结点的“重要性”计算 (30 分)   在社交网络中,个人或单位(结点)之间通过某 ...

  7. PTA 7-7 六度空间 (30分)

    PTA 7-7 六度空间 (30分) "六度空间"理论又称作"六度分隔(Six Degrees of Separation)"理论.这个理论可以通俗地阐述为:& ...

  8. 二叉搜索树的结构(30 分) PTA 模拟+字符串处理 二叉搜索树的节点插入和非递归遍历

    二叉搜索树的结构(30 分) PTA 模拟+字符串处理 二叉搜索树的节点插入和非递归遍历   二叉搜索树的结构(30 分) 二叉搜索树或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则 ...

  9. PTA 05-树9 Huffman Codes (30分)

    题目地址 https://pta.patest.cn/pta/test/16/exam/4/question/671 5-9 Huffman Codes   (30分) In 1953, David ...

随机推荐

  1. Permutations(copy)

    Given a collection of numbers, return all possible permutations. For example, [1,2,3] have the follo ...

  2. Android笔记--Bitmap(三) 针对不用Android版本的位图管理

    Bitmap(三) | Android不同版本的相应操作 在不同的Android版本中.位图的存储方式是不同的. 1.小于等于 Android 2.2 (API level 8) 垃圾收集器回收内存时 ...

  3. 【extjs6学习笔记】0.0 准备

    1.下载ExtJS 6 下面是Ext JS 6正式版的GPL版本下载地址 https://www.sencha.com/legal/gpl/ 2.下载sencha cmd 安装完成后,命令行运行出现以 ...

  4. UVALive 3211 Now or Later (2-SAT)

    题目的要求一个最小值最大,二分即可,但是怎么判断呢? 飞机早或者晚两种状态,可以用一个布尔变量表示,假设当前猜测为m,那么根据题意, 如果x和y所对应的时间冲突那么就是¬(xΛy)化成或的形式(¬x) ...

  5. Codeforces Round #318 (Div. 2) C Bear and Poker (数学)

    简单题,求一下所有数的2和3的幂是任意调整的,把2和3的因子除掉以后必须相等. 求lcm,爆了long long.我得好好反省一下,对连乘不敏感 #include<bits/stdc++.h&g ...

  6. tomcat假死现象 - 二

    1 编写背景 最近服务器发现tomcat的应用会偶尔出现无法访问的情况.经过一段时间的观察最近又发现有台tomcat的应用出现了无法访问情况.简单描述下该台tomcat当时具体的表现:客户端请求没有响 ...

  7. Spring框架针对dao层的jdbcTemplate操作crud之query查询数据操作

    查询目标是完成3个功能: (1)查询表,返回某一个值.例如查询表中记录的条数,返回一个int类型数据 (2)查询表,返回结果为某一个对象. (3)查询表,返回结果为某一个泛型的list集合. 一.查询 ...

  8. 选择法数组排序参考(Java)

    package com.swift; public class Xuanze { public static void main(String[] args) { int[] arr= {28,2,3 ...

  9. Swift 中 String 与 CChar 数组的转换

    在现阶段Swift的编码中,我们还是有很多场景需要调用一些C函数.在Swift与C的混编中,经常遇到的一个问题就是需要在两者中互相转换字符串.在C语言中,字符串通常是用一个char数组来表示,在Swi ...

  10. MySQL Group Replication(组复制MGR)

    MGR基本要求: 1.InnoDB存储引擎 2.主键,每个表必须具有已定义的主键或等效的主键,其中等效项是非null唯一键 3.IPv4网络 4.网络性能 5.开启二进制日志并开启GTID模式 6.m ...