PTA 08-图9 关键活动 (30分)
题目地址
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分)的更多相关文章
- PTA 7-2 哈夫曼编码 (30分)
PTA 7-2 哈夫曼编码 (30分) 给定一段文字,如果我们统计出字母出现的频率,是可以根据哈夫曼算法给出一套编码,使得用此编码压缩原文可以得到最短的编码总长.然而哈夫曼编码并不是唯一的.例如对字符 ...
- PTA 11-散列4 Hard Version (30分)
题目地址 https://pta.patest.cn/pta/test/16/exam/4/question/680 5-18 Hashing - Hard Version (30分) Given ...
- 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 ...
- PTA 逆散列问题 (30 分)(贪心)
题目链接:https://pintia.cn/problem-sets/1107178288721649664/problems/1107178432099737614 题目大意: 给定长度为 N 的 ...
- PTA 社交网络图中结点的“重要性”计算(30 分)
7-12 社交网络图中结点的“重要性”计算(30 分) 在社交网络中,个人或单位(结点)之间通过某些关系(边)联系起来.他们受到这些关系的影响,这种影响可以理解为网络中相互连接的结点之间蔓延的一种相互 ...
- PTA数据结构与算法题目集(中文) 7-36 社交网络图中结点的“重要性”计算 (30 分)
PTA数据结构与算法题目集(中文) 7-36 社交网络图中结点的“重要性”计算 (30 分) 7-36 社交网络图中结点的“重要性”计算 (30 分) 在社交网络中,个人或单位(结点)之间通过某 ...
- PTA 7-7 六度空间 (30分)
PTA 7-7 六度空间 (30分) "六度空间"理论又称作"六度分隔(Six Degrees of Separation)"理论.这个理论可以通俗地阐述为:& ...
- 二叉搜索树的结构(30 分) PTA 模拟+字符串处理 二叉搜索树的节点插入和非递归遍历
二叉搜索树的结构(30 分) PTA 模拟+字符串处理 二叉搜索树的节点插入和非递归遍历 二叉搜索树的结构(30 分) 二叉搜索树或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则 ...
- 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 ...
随机推荐
- 浅谈Hibernate中的三种数据状态
Hibernate中的三种数据状态:临时.持久.游离 1.临时态(瞬时态) 不存在于session中,也不存在于数据库中的数据,被称为临时态. 数据库中没有数据与之对应,超过作用域会被JVM垃圾回收器 ...
- git代理设置方法
客户公司办公,上外网需要代理,临时查一下资料,记录一下: 1.设置代理: git config --global http.proxy http://IP:Port 2.代理设置完成后,查看设置是否生 ...
- 关于js对象中的,属性的增删改查问题
删除主要是delet方法: 1 function Person(){}; 2 var person = new Person(); 3 person.name = 'yy'; 4 person.gen ...
- sparkmlib-相关系数
一.基本原理 在stat包中实现了皮尔逊(Pearson)与 斯皮尔曼(Spearman)两类相关系数的计算 (1)Pearson: (x,y)协方差/[(x标准方差)*(y标准方差)] 详情可以 ...
- WPF中在后台实现控件样式
加入现在有一个Button的样式如下: <Style TargetType="{x:Type Button}" x:Key="MyButton">. ...
- vue cli的安装与使用
一.简介 vue作为前端开发的热门工具,受到前端开发人员的喜爱.为了简化项目的构建,采用vue cli来简化开发. vue cli是一个全局安装的npm包,提供了终端使用的命令.vue create可 ...
- CAD交互绘制mcdbsolid对象(网页版)
主要用到函数说明: _DMxDrawX::DrawSolid 绘McDbSolid对象.详细说明如下: 参数 说明 DOUBLE dX1 第一个点X DOUBLE dY1 第一个点Y DOUBLE d ...
- mysql dump 参数大全
Mysqldump参数大全 摘自:https://www.cnblogs.com/qq78292959/p/3637135.html 参数 参数说明 --all-databases , -A 导 ...
- 利用React遍历数组,并且用数组的元素生成<li>arrItem</li>标签组
var numbers = [1,2,3,4,5,6,7,8,9]; ReactDom.render({ <ul> { numbers.map(function(item){ return ...
- MYSQL中批量替换某个字段的部分数据
1.修改字段里的所有含有指定字符串的文字 UPDATE 表A SET 字段B = replace(字段B, 'aaa', 'bbb') example: update table set url= ...