关键路径 p3 清华复试上机题

题目描述

小H为了完成一篇论文,一共要完成n个实验。其中第i个实验需要a[i]的时问去完成。小H可以同时进行若干实验,但存在一些实验,只有当它的若干前置实验完成时,才能开始进行该实验。同时我们认为小H在一个实验的前置实验都完成时,就能马上开始该实验。

为了让小H 尽快完成论文,需要知道在最优的情况下,最后一个完成的实验什么时候完成。

小H还想知道,在保证最后一个实验尽快完成的情况下(即保证上一间的答案不变),他想知道每个实验最晚可以什么时候开始。

设第i个实验最早可能的开始时问为fi,不能响最后一个实验完成时间的最晚开始时间为gi,请证明\(\prod_{i=0}^{n}(g_i-f_i+1)\)除以\(10^9+7\)所得的余数能够保证题目有解。

输入

从标淮输入读入数据。

第一行输入两个整数n,m。

第二行输入n个正整数 a,a[2],…,a[n],描述完成每个实验所需要的时间。

接下来读入 m 行,每行读入两个整数u,v,表示编号为u的实验是编号为v的实验的前置实验。

对于所有的输入数据,都满足\(1\leqslant n \leqslant 10^5\),\(1\leqslant m \leqslant 5×10^5\),\(1\leqslant a_i\leqslant 10^6\).

输出

输出到标准输出。

第一行输出一个整数,表示完成实验的时间。

第二行输出一个整数表示\(\prod_{i=0}^{n}(g_i-f_i+1)\)除以\(10^9+7\)所得的余数。

样例输入

7 5

11 20 17 10 11 17 17

5 4

6 1

7 3

2 4

2 1

样例输出

34

7840

解题思路

求关键路径的长度,记录每个实验最早开始时间和最晚开始时间。典型关键路径问题。

代码实现

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const int maxn = 1e5 + 7;
const int INF = INT_MAX;
const int MOD = 1e9 + 7; vector<int> graph[maxn];
int inDegree[maxn];
ll earliest[maxn];
ll latest[maxn];
ll timee[maxn]; ll criticalPath(int n) {
vector<int> topology;
queue<int> q;
for (int i = 1; i <= n; ++i) {
if (inDegree[i] == 0) {
q.push(i);
}
}
ll totalTime = 0;//总耗时
while (!q.empty()) {
int u = q.front();
topology.push_back(u);
q.pop();
for (int i = 0; i < graph[u].size(); ++i) {
int v = graph[u][i];
inDegree[v]--;
earliest[v] = max(earliest[v], timee[u] + latest[u]);//取最大值的原因:只有当前结点的所有前驱结点活动全部完成,才能完成本结点
if (inDegree[v] == 0) {
q.push(v);
totalTime = max(totalTime, earliest[v] + timee[v]);//关键路径长度为最大路径长度的路径
}
}
}
for (int i = topology.size() - 1; i >= 0; --i) {//逆拓扑排序求最迟开始时间
int u = topology[i];
if (graph[u].size() == 0) {
latest[u] = totalTime - timee[u];//出度为0的点,最晚开始时间为关键路径长度减去其耗费时间
} else {
latest[u] = INF;//后面要求最小值,初始化为极大值
}
for (int j = 0; j < graph[u].size(); ++j) {
int v = graph[u][j];
latest[u] = min(latest[u], latest[v] - timee[u]);//非出度为0的点,最晚开始时间为所有其后续节点最晚开始时间减去该节点耗费时间的最小值
}
}
return totalTime;
} int main() {
int n, m;
while (cin >> n >> m) {
memset(graph, 0, sizeof graph);
memset(inDegree, 0, sizeof inDegree);
memset(earliest, 0, sizeof earliest);
memset(latest, 0, sizeof latest);
memset(timee, 0, sizeof timee);
for (int i = 1; i <= n; i++) {
cin >> timee[i];
}
while (m--) {
int from, to;
cin >> from >> to;
graph[from].push_back(to);
inDegree[to]++;
}
ll totalTime = criticalPath(n);
ll answer = 1;
for (int i = 1; i <= n; ++i) {
answer *= latest[i] - earliest[i] + 1;
answer %= MOD;
}
cout << totalTime << endl << answer << endl;
}
return 0;
}

关键路径 p3 清华复试上机题的更多相关文章

  1. Twin Prime Conjecture(浙大计算机研究生保研复试上机考试-2011年)

    Twin Prime Conjecture                                            Time Limit: 2000/1000 MS (Java/Othe ...

  2. HDU 1234 (浙大计算机研究生复试上机考试-2005年) 开门人和关门人 (水)

    开门人和关门人 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Su ...

  3. ZOJ问题(2010浙江大学研究生复试上机题目[找规律] hdoj 3788)

    ZOJ问题 pid=3788">点击打开链接 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K ...

  4. Java上机题(封装)(编写student类)

    今天帮大一的童鞋写Java上机题 题目虽然很简单,但是刚拿到题目的时候愣了一下,然后就疯狂get set QuQ 其实这是一个特别基本的封装的题目(之前实验室面试大二的时候竟然还有蛮多人不知道封装的概 ...

  5. Python语言上机题实现方法(持续更新...)

    Python语言上机题实现方法(持续更新...) 1.[字符串循环左移]给定一个字符串S,要求把S的前k个字符移动到S的尾部,如把字符串"abcdef"前面的2个字符'a'.'b' ...

  6. Java 哈希表(google 公司的上机题)

    1 哈希表(散列)-Google 上机题 1) 看一个实际需求,google 公司的一个上机题: 2) 有一个公司,当有新的员工来报道时,要求将该员工的信息加入(id,性别,年龄,住址..),当输入该 ...

  7. 九度OJ1486 /POJ 1029/2012北京大学研究生复试上机

    wa到死!wa到死!这是一个看着简单,坑及其多的题! 坑一:POJ上是单组输入,九度上是多组输入,妈蛋要是研究生复试遇到这种大坑肯定死掉啊!而且对于codeforces比较习惯的 同学肯定会觉得巨坑无 ...

  8. 华为上机题汇总----java

        以下华为上机题目都是网上整理得到的,代码都是自己调试过的,由于网上java答案较少,欢迎大家批评指正,也希望对准备华为上机的童鞋们有一点点帮助.在练习的过程中成长,加油!~~  第1题:输入字 ...

  9. 浙江大学PAT上机题解析之1014. 福尔摩斯的约会 (20)

    1014. 福尔摩斯的约会 (20) 时间限制   50 ms 内存限制   32000 kB 代码长度限制   8000 B 判题程序     Standard     作者     CHEN, Y ...

随机推荐

  1. 文档声明(Doctype)和<!Doctype html>有何作用? 严格模式与混杂模式如何区分?它们有何意义?

    文档声明的作用: 文档声明是为了告诉浏览器,当前HTML文档使用什么版本的HTML来写的,这样浏览器才能按照声明的版本来正确的解析. <!doctype html> 的作用就是让浏览器进入 ...

  2. SpringMVC-设置编码过滤器

    1.接上文->springmvc获取请求参数链接 2.在web.xml配置编码过滤器 <!-- 配置编码过滤器--> <filter> <filter-name&g ...

  3. QT-notepad++仿写

    最近小忙,准备学习下FFMPEG 涉及:工具栏使用,QAction,文件基本读写操作 Github地址:https://github.com/wsdassssss/notepad-

  4. Markdown基础语法规则

    你好,世界.粗体,斜体,测试,弟弟,H2O 论文题目 一级标题 二级标题 三级标题 1 2 3 点击此链接打开网址 公式 \(y = \sin x\) \[ y = \frac{1}{x} \] dd ...

  5. 最大数maxnumber - 题解【树状数组】

    原题: 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作.语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值.限制:L不超过当前数列的长度. 2. 插入操作.语法 ...

  6. 【转】python代码优化常见技巧

    https://blog.csdn.net/egefcxzo3ha1x4/article/details/97844631

  7. 想法子记忆Vi/Vim常用操作及指令

    本笔记有特殊目录,点击开启: 专有目录 在Linux系统中编辑文本总是离不开一位老帮手--Vi.而因为其诞生的年代有些久远,有些操作在现在看来可能有点"反直觉". 于是我决定写这样 ...

  8. python基础-基本数据类型(三)

    一.散列类型 散列类型用来表示无序的集合类型 1.集合(set) Python中的集合与数学符号中的集合类似,都是用来表示无序不重复元素的集合. 1.1 集合的定义 集合使用一对{}来进行定义,集合中 ...

  9. LINUX系统虚拟机环境的安装

    安装VM和Centos Step 1 去BIOS里修改设置开启虚拟化设备支持 设置BIOS: 1.开机按F2.F12.DEL.ESC等进入BIOS,一般来说可以看屏幕的左下角有提示按键进入BIOS,进 ...

  10. 1.3 Linux和UNIX的关系及区别(详解版)

    UNIX 与 Linux 之间的关系是一个很有意思的话题.在目前主流的服务器端操作系统中,UNIX 诞生于 20 世纪 60 年代末,Windows 诞生于 20 世纪 80 年代中期,Linux 诞 ...