南大算法设计与分析课程OJ答案代码(5)--割点与桥和任务调度问题
问题 A: 割点与桥
时间限制: 1 Sec 内存限制: 5 MB
提交: 475 解决: 34
提交 状态 算法问答
题目描述
输入
第一行:点的个数,如果点个数是n,他们的编号为0 ~ n-1
余下的行:每行代表一条边,如“0 2”代表顶点0和顶点2有一条边 (一条边只出现一次,如出现“0 2”则不会出现“2 0”)
输出
这次需要大家先输出一个字符串,它是“我已阅读关于抄袭的说明”的汉语拼音.输出此行的提交我们将认为已经完全阅读并了解了“关于抄袭的说明”公告.
所有的割点和所有的桥,先输出割点再输出桥
割点按编号升序排列,桥按边的升序排列,如“0 2”小于“0 3”,“1 5”小于“2 3”(边的输出和排列总是把小顶点放前面,所以输出总是“0 2”而非“2 0”)
样例输入5 |
样例输出wo yi yue du guan yu chao xi de shuo ming |
提示
两个算法的伪代码书上都有了,就不多说了。
这个题比较坑的地方是空间复杂度,开始保存图一直使用的set<int>,一直不过,改成vector<int>就过了
本题中,为了节省空间,我尽量使用了new,在染色节点的时候,我直接使用了discovertime来表示,当discovertime==0时表示节点未访问,discovertime<0表示正在访问,discovertime>0时表示访问结束。所以在DFS刚访问节点设置discovertime时,我将discovertime设置为-time,结束时去绝对值。
答案
#include <iostream>
#include <map>
#include <set>
#include <vector>
#include <algorithm>
using namespace std; //找割点
void DFS_find_cutvertex(vector<int>* g, int point, int time, pair<int, int>* times,vector<int> & result,int& treenum,int parent) {
++time;
//在访问节点是,将back设为当前时间
times[point].second = time * -;
times[point].first = time;
//节点染成灰色
for (auto i = g[point].begin(); i!= g[point].end(); i++) {
//到此时,此时i表示需要遍历的下一个邻居节点
int y = *i;
if (times[*i].second == ) {
if (point == ) treenum++;
DFS_find_cutvertex(g, *i, time, times,result,treenum,point);
//判断是否为割点
if (times[*i].first >= abs(times[point].second) && point != )
result.emplace_back(point);
times[point].first = min(times[point].first, times[*i].first);
}else {
//正在被访问,这能代表BF的边?
if (times[*i].second < && *i != parent) {
times[point].first = min(times[point].first, abs(times[*i].second));
}
}
}
//节点染成黑色
times[point].second = abs(times[point].second);
} //找桥,对寻找割点的程序简单修改
void DFS_find_bridge(vector<int>* g, int point, int time, pair<int, int>* times, vector<pair<int,int>> & result,int parent) {
++time;
//当discovertime为负数时,表示正在被访问
times[point].second = time * -;
times[point].first = time;
for (auto i = g[point].begin(); i != g[point].end(); i++) {
if (times[*i].second == ) {
DFS_find_bridge(g, *i, time, times, result,point);
times[point].first = min(times[point].first, times[*i].first);
if (times[*i].first > abs(times[point].second)) {
//保持结果中的边小的点在前
if(point < *i) result.emplace_back(pair<int, int>(point, *i));
else result.emplace_back(pair<int, int>(*i,point));
}
}
else {
if (times[*i].second < && *i != parent) {
times[point].first = min(times[point].first, abs(times[*i].second));
}
}
}
//节点染成黑色
times[point].second =abs(times[point].second);
} int main()
{
int point_num = ;
cin >> point_num;
//times的first和second用来存放寻找割点时保存的back值和discovertime
pair<int, int>* times = new pair<int, int>[point_num];
//每个点能到达的其他点
vector<int>* g = new vector<int>[point_num]; int in = ;
int out = ;
while (cin >> in && cin >> out) {
g[in].emplace_back(out);
g[out].emplace_back(in);
} //DFS寻找割点
int time = ;
vector<int> result;
int treenum = ;
DFS_find_cutvertex(g,,time, times, result,treenum,-);
if (treenum >= )
result.emplace_back();
sort(result.begin(),result.end()); //将节点全部染成白色.时间重置
for (auto i = ; i < point_num; i++) {
times[i].first = ;
times[i].second = ;
} //DFS寻找桥
int time2 = ;
vector<pair<int,int>> result2;
DFS_find_bridge(g, , time2, times, result2, -);
sort(result2.begin(), result2.end()); cout << "wo yi yue du guan yu chao xi de shuo ming" << endl;
for (auto i = ;i<result.size();i++)
cout << int(result[i]) << endl;
for (auto i = ; i < result2.size(); i++) {
cout << int(result2[i].first) << " " << int(result2[i].second) << endl;
} delete []times;
delete []g;
return ;
}
问题 B: 任务调度问题
时间限制: 1 Sec 内存限制: 5 MB
提交: 168 解决: 39
提交 状态 算法问答
题目描述
请大家在做oj题之前,仔细阅读关于抄袭的说明http://www.bigoh.net/JudgeOnline/.
算法助教实在是太忙了,每天有n个事情要做,但他觉得自己一件一件的做实在是太蠢了,所以想找一些班上的同学来帮忙一块做这些事。
在分配任务的过程中他发现,这n个任务中有一些任务的开始需要依赖另一些任务的完成,例如,当只有先批改完算法作业(记为事件A),才能给大家登记作业成绩(记为事件B),这时我们就可称事件B依赖于事件A。机智的他利用了算法课上的知识,采用有向图中的节点来表示这些事件,并且利用图中的边来表示这些事件的依赖关系,例如,当事件B依赖于事件A时,图中就存在一条由B指向A的边。助教还对这样的有向图进行了升级,用节点的权值表示完成每个事件所需要的时间。
然而,随后他发现,由于图中依赖关系的存在,即使他利用庞大的关系网能找来无穷多个同学帮他做这些事,完成所有事件的最短时间也是确定的。那么问题来了,助教每天要花多少时间来处理这n个事情呢?这时,助教想起了算法课上学到的关键路径的定义似乎能够帮他解决这个问题。聪明的同学们,你们能告诉助教他即使找到帮手,每天做完这n个事情最短也需要花多长时间吗?
(善良的助教已经帮你们把这些事情建模成有向图,如输入所示。)
输入
第一行为图中的顶点个数n
第二行至第n+1行为每个顶点代表的事件编号(事件编号为1至n)及完成该事件所需的时间。 如,“1 50”代表完成事件1需要50个单位时间。
余下的行中,每一行表示一个依赖关系,例如,“1 3” 表示事件1的完成依赖于事件3的完成。
输出
这次依旧需要大家输出一行字符串,它还是“我已阅读关于抄袭的说明”的英文翻译,即:"I have read the rules about plagiarism punishment"。输出此行的提交我们将认为已经完全阅读并了解了“关于抄袭的说明”公告并同意关于抄袭的惩罚措施。
第二行输出完成所有这n个任务所需最短的执行时间。
样例输入9 |
样例输出I have read the rules about plagiarism punishment |
提示
如果这些事情出现了循环依赖,则助教永远也不可能做完这些事(好惨 TAT)。所以你可以大胆假定,助教要做的这些事情中并不存在循环依赖,也就是说,输入的图一定是一个有向无环图。
答案
算法同样在书上有,就不多说了。
这里需要注意的就是在DFS上需要加wapper,遍历每个节点,找出最大的最早结束时间,注意,在遍历完一个节点后,不要清除visited和时间内容,这样遍历下一个节点时能减少工作量。
具体各对象的实现就看代码吧
#include <iostream>
#include <map>
#include <set>
#include <vector>
#include <algorithm>
using namespace std; //g表示图,point表示遍历开始节点,times表示各点最早开始结束时间,visited表示节点访问状态,result表示最大的最早结束时间
void DFS_critical_path(vector<int>* g, int point, pair<int, int>* times, vector<int>& visited, vector<int>& cost) {
visited[point] = ;
times[point].first = ;
for (auto i = g[point].begin(); i != g[point].end(); i++) {
if (visited[*i] == ) {
DFS_critical_path(g, *i, times,visited,cost);
if (times[*i].second >= times[point].first) {
times[point].first = times[*i].second;
} }else {
if (times[*i].second >= times[point].first) {
times[point].first = times[*i].second;
}
}
}
//节点染成黑色
times[point].second = times[point].first + cost[point];
visited[point] = ;
} int main()
{
int point_num = ;
cin >> point_num;
vector<int> cost(point_num,);
int num = ;
int c = ; //v[i].first表示最早开始时间,v[i].second表示最早结束时间
pair<int, int>* times = new pair<int, int>[point_num]; //visited[i] == 0表示节点未访问,visited == 1 表示节点正在访问,visited == 2表示访问结束
vector<int> visited(point_num, ); ////path[i] == 0表示i不是关键路径,path[i] == 1表示i是关键路径
//vector<int> path(point_num, 0); //获取每个事件的花费
for (int i = ; i < point_num; i++) {
cin >> num;
cin >> c;
cost[i] = c;
}
//将A依赖于B表示成图中有B到A的单向边,g[i]表示点i能到达的所有点
vector<int>* g = new vector<int>[point_num];
while (cin >> num && cin >> c) {
//输入是从1开始,但数组索引是从0开始
g[num-].emplace_back(c-);
} /*cost = {10,6,5,1,2,3,4,9,1,20};
g[0] = {8};
g[1] = {0,7};
g[2] = {4,5,6};
g[3] = {1,2};
g[4] = {8};
g[5] = {8};
g[6] = {8};
g[7] = {8};
g[8] = {};
g[9] = { 7 };
begin[3] = 1;
begin[9] = 1;*/ //DFS遍历,从所有节点都做一遍DFS,找出最大的最晚结束时间
int result = ;
for (int i = ; i < point_num; i++) {
DFS_critical_path(g, i, times, visited, cost);
if (times[i].second > result)
result = times[i].second;
} cout << "I have read the rules about plagiarism punishment" << endl;
cout << result << endl; delete[]times;
delete[]g;
}
南大算法设计与分析课程OJ答案代码(5)--割点与桥和任务调度问题的更多相关文章
- 南大算法设计与分析课程OJ答案代码(3)
问题 A: 动态中位数问题 时间限制: 1 Sec 内存限制: 8 MB提交: 866 解决: 102提交 状态 算法问答 题目描述 输入一组整数a1, a2, …, an ,每输入一个整数,输出 ...
- 南大算法设计与分析课程OJ答案代码(4)--变位词、三数之和
问题 A: 变位词 时间限制: 2 Sec 内存限制: 10 MB提交: 322 解决: 59提交 状态 算法问答 题目描述 请大家在做oj题之前,仔细阅读关于抄袭的说明http://www.bi ...
- 南大算法设计与分析课程OJ答案代码(2)最大子序列和问题、所有的逆序对
问题 A: 最大子序列和问题 时间限制: 1 Sec 内存限制: 4 MB提交: 184 解决: 66提交 状态 算法问答 题目描述 给定一整数序列 a1, a2, …, an,求 a1~an 的 ...
- 南大算法设计与分析课程OJ答案代码(1)中位数附近2k+1个数、任意两数之和是否等于给定数
问题1 用来测试的,就不说了 问题2:中位数附近2k+1个数 给出一串整型数 a1,a2,...,an 以及一个较小的常数 k,找出这串数的中位数 m 和最接近 m 的小于等于 m 的 k 个数,以及 ...
- 南大算法设计与分析课程复习笔记(1) L1 - Model of computation
一.计算模型 1.1 定义: 我们在思考和处理算法的时候是机器无关.实现语言无关的.所有的算法运行在一种“抽象的机器”之上,这就是计算模型. 1.2 种类 图灵机是最有名的计算模型,本课使用更简单更合 ...
- 南大算法设计与分析课程复习笔记(4)L4 - QuickSort
一.快速排序 算法导论上关于快速排序有两种写法 第一种,从头到尾遍历,不断将小于基准元素的项移到前面.代码很简介,只需要维护一个交换位置,表示小于基准元素的末尾位置加一 我们看算法导论上的一个例子: ...
- 南大算法设计与分析课程复习笔记(3)L3 - Recursion
一.递归方程 按照分治的思想,可以将一个递归的复杂度写成递归方程 一.解递归方程--猜然后证明 该方法又称为代入法,步骤如下: 1.猜解的形式 2.数学归纳法证明正确 例子: 我们假设有如下递归式: ...
- 南大算法设计与分析课程复习笔记(2)L2 - Asymptotics
一.几种比较复杂度的符号 数据结构有描述,相关严格数学定义也不想说了,就这么过了吧. 二.最大子数组的几种解决方法 从最复杂的暴力解法过渡到最简单的动态规划 解析和代码见这里:http://www.c ...
- 算法设计与分析 - AC 题目 - 第 5 弹(重复第 2 弹)
PTA-算法设计与分析-AC原题 - 最大子列和问题 (20分) 给定K个整数组成的序列{ N1, N2, ..., NK },“连续子列”被定义为{ Ni, Ni+, ..., Nj },其中 ≤i ...
随机推荐
- easyui的下拉框combox动态复赋值显示在前端
editbale:false设置为本输入框禁止编辑
- FPGA学习之旅
从大学就开始使用stm32,工作之后,仍然没有摆脱,从f1系列,到f4系列,然后又到L1系列,尽管可以满足工作需要,但还是希望可以摆脱束缚,尝试学习FPGA,希望能够遇到一个好机遇.
- 吴恩达机器学习笔记29-神经网络的代价函数(Cost Function of Neural Networks)
假设神经网络的训练样本有
- Python学习笔记【第九篇】:Python面向对象基础
Python语言中一切皆对象(类.属性.方法.........) 概念 面向对象编程:Object Oriented Programming 简称OOP 面向对象程序设计 面向对象和面向过程都是解决问 ...
- 《http权威指南》读书笔记11
概述 最近对http很感兴趣,于是开始看<http权威指南>.别人都说这本书有点老了,而且内容太多.我个人觉得这本书写的太好了,非常长知识,让你知道关于http的很多概念,不仅告诉你怎么做 ...
- Mysql实现树形递归查询
最近在做项目迁移,Oracle版本的迁到Mysql版本,遇到有些oracle的函数,mysql并没有,所以就只好想自定义函数或者找到替换函数的方法进行改造. Oracle递归查询 oracle实现递归 ...
- wav转txt格式的代码实现(c,python)
平时经常做音频算法,经常用得到wav转txt的转换,这里就做个备忘,自己写了一些小代码来实现这个目标: 第一个是c代码的实现: #include <stdio.h> #include &l ...
- 解决Database returned an invalid datetime value. Are time zone definitions for your database installed?
设定博客文章按照时间分层筛选出现问题 ret=Article.objects.filter(user=user).annotate(month=TruncMonth("create_time ...
- remote: Incorrect username or password ( access token )
解决问题 进入控制面板 用户账号,选择管理您的凭据 修改凭据 修改完成后,保存即可
- 引入CSS的三种方式
虽然入职已经大半年,并自诩前端工程师,但是我真的不会……(有一种我有罪我该死的感觉 从CSS 样式代码插入的形式来看基本可以分为以下3种:内联式.嵌入式和外部式三种. 1.内联式 内联式css样式表就 ...