[日常训练] 保存名画
2017-07-19 17:21
211 查看
【问题描述】
在一个Byteland上有一副非常有名的图画需要被封存。这个作品需要在2个实验室进行处理。这个处理过程被分为许多步骤。对于每个步骤,我们知道它必须要在哪个实验室进行。在两个实验室之间运输这些这些美丽但又易碎的画会带来额外的风险,因此这个运输的过程需要尽可能的被避免。理想情况下所有的工作都会在第一个实验室做完,然后剩下的在另一个实验室完成,但是有些步骤必须在另一步骤完成之后才能完成。你的任务是找到一个工作的顺序,让这个被运输的过程最少。输出需要运输的次数。
【输入格式】
第一行N和M,代表着N个步骤,和M个先后关系。下面一行N个数字,第I个数字是1或2,代表了第I个工作需要在哪个实验室完成,下面M行I,J,代表了第I个工作必须在第J个工作前完成。你可以认为这个题目必有解
【输出格式】
输出最少需要的运输次数。【输入样例】
5 61 2 1 2 1
1 2
1 3
2 4
3 4
2 5
3 5
【输出样例】
2【数据范围与约定】
30%数据保证n<=5。100%数据中n<=100000,m<=1000000。
【30分】全排列搜索
【100分】拓扑排序 + 贪心
对于第1或第2个实验室,我们分别建两个队列存储当前进行能够在第1或第2个实验室完成的工作。然后进行拓扑排序:[1]、每次选取入度为0的点加入两个队列;
[2]、要使运输次数最少,就肯定要尽量在同一个队列里选取能完成的步骤,因此记一个状态st,表示当前我们所选取的是第st个队列;
[3]、每次从第st个队列中取出队头元素作为进行的步骤,那么在该步骤之后完成的步骤入度都要减少1;
[4]、如果一个队列为空,表示现在我们已经不能一直在同一个实验室里完成一些步骤,因此要换一个队列来取出队头元素,同时运输次数加一,直到两个队列都为空为止。
另外因为st的最初值可能为1或2(最初可能在任意一个实验室里),所以对于这两种情况,我们都要计算一遍,最后对两者取一个最小值。
【代码】
#include <iostream> #include <cstdio> using namespace std; const int N = 1e5 + 5, M = 1e6 + 5; int rin , cur , a , n, m; int lst , nxt[M], to[M], T; inline int get() { int res; char ch; while ((ch = getchar()) < '0' || ch > '9'); res = ch - '0'; while ((ch = getchar()) >= '0' && ch <= '9') res = (res << 3) + (res << 1) + ch - '0'; return res; } inline int Min(const int &x, const int &y) {return x < y ? x : y;} inline void ad b1c6 dEdge(const int &x, const int &y) { nxt[++T] = lst[x]; lst[x] = T; to[T] = y; rin[y]++; } inline int Query(int st) { static int Q [2], t[2], w[2]; int x, y, Ans = 0; t[0] = t[1] = w[0] = w[1] = 0; for (int i = 1; i <= n; ++i) cur[i] = rin[i]; for (int i = 1; i <= n; ++i) if (!cur[i]) Q[++w[a[i]]][a[i]] = i; while (t[0] < w[0] || t[1] < w[1]) { if (t[st] == w[st]) st ^= 1, Ans++; x = Q[++t[st]][st]; for (int i = lst[x]; i; i = nxt[i]) if (!(--cur[y = to[i]])) Q[++w[a[y]]][a[y]] = y; } return Ans; } int main() { freopen("save.in", "r", stdin); freopen("save.out", "w", stdout); n = get(); m = get(); int x, y; for (int i = 1; i <= n; ++i) a[i] = get() - 1; while (m--) { x = get(); y = get(); addEdge(x, y); } printf("%d\n", Min(Query(0), Query(1))); fclose(stdin); fclose(stdout); return 0; }
相关文章推荐
- TensorFlow1.5训练模型的保存与加载
- 日常训练 20170708 假如爱有天意love
- [日常训练] 压缩
- 日常训练20161012 方块游戏
- Wikioi 3345 保存名画(拓扑排序)
- TensorFlow 深度学习框架(7)-- 变量管理及训练模型的保存与加载
- [日常训练] Lost My Music
- DeepLearning tutorial(2)机器学习算法在训练过程中保存参数
- caffe保存训练log日志文件并利用保存的log文件绘制accuary loss曲线图
- 日常训练 平均数
- 日常训练—cf 2017 USP Try-out
- 日常训练 腐女的生日 奥妙重重的最短路
- 日常训练 20170606 极地旅行社
- 日常训练 20170622 数字游戏
- 几种保存训练模型文件类型
- [日常训练] 坦克
- [日常训练] 魔法传输
- 周六日常训练,背包dp,树形dp,简单dp以及很多数学?
- 日常训练20161014 成绩调研
- TensorFlow训练的模型参数(W和B)利用np.savez()保存和用cnpy库C++读取