赞
踩
| 过程 |
|---|
| 1. 先搞出一个拓扑序 |
| 2. 计算最早开始时间 利用拓扑序从源点开始跑 |
| 依次求出每个点的邻接点的最早开始时间 若b是a的邻接点 |
| Earliest[b] = max(Earliest[a] + a.weight,Earliest[b]); |
| a的最最早开始时间+ a到b的权重 默认最早开始时间是0 |
| 最早完成时间 : 要等之前的节点最慢的那个完了之后才能开始这个节点 |
| 3. 由第二步即可知道路径长度,最后一个节点的完成时间就是 |
| 若还要求关键路径: |
| 4. 先求最晚开始时间 (为了当前的节点和下一个节点的最早开始时间之间 有没有空余) |
| 5. 从结尾反向扫描到源点 求出最早开始时间和最晚开始时间之间的间隔 |
| 6. 最后找到一个间隔为0的路径 这个路径就是关键路径 |

| 注释很详细 |
|---|
#include <iostream> #include <vector> #include <algorithm> using namespace std; struct edge { int x, y; int weight; }; struct Activity { edge e; // 最早时间和最晚时间的延迟 int d; }; // 正向图 反向图 // 反向图求最晚结束时间用 vector<vector<edge>> rode, Rrode; // 拓扑排序 vector<int> topoOrder; vector<int> vis; // 最早开始时间 vector<int> Earliest; // 最晚开始时间 vector<int> Latest; vector<Activity> Delay; int N, M; // 拓扑排序 bool dfs(int k) { vis[k] = 1; for (auto e : rode[k]) { if (vis[e.y] == 1) return false; if (!vis[e.y] && !dfs(e.y)) return false; } vis[k] = -1; topoOrder.push_back(k); return true; } bool TopSort() { for (int i = 0; i < N; i++) { if (!vis[i] && !dfs(i)) { return false; } } return true; } int CriticalPath() { // 路径长度 int res = 0; // 因为DFS的拓扑序是反着的 反过来搞一下 reverse(topoOrder.begin(), topoOrder.end()); // 最早开始时间默认为0 fill(Earliest.begin(), Earliest.end(), 0); // 求最早开始时间 - 从源点开始扫描拓扑序 for (auto e : topoOrder) { // 对于x的每个邻接点 for (auto x : rode[e]) { // 因为要保证节点 x.y 之前的每个节点都处理完 // 所以找一个最晚完成的 if (Earliest[x.y] < Earliest[e] + x.weight) { // x.y 的时间 = y的一个入点e + e->e.y 的权重 Earliest[x.y] = Earliest[e] + x.weight; } } } // 最后一个节点的最早完成时间就是路径长度 res = Earliest[topoOrder[topoOrder.size() - 1]]; // 最晚开始时间默认大一点 因为一共就是res嘛 那就 res咯 fill(Latest.begin(), Latest.end(), Earliest[topoOrder.size() - 1]); // 最晚开始时间得从结尾往源点搜索 reverse(topoOrder.begin(), topoOrder.end()); // 一样是访问邻接点 不过这次的反着的 for (auto e : topoOrder) { for (auto x : Rrode[e]) { // 最晚开始时间是当前节点x的最早开始时间 - x->x.y的路径 // 要最小的 if (Latest[x.y] > Latest[x.x] - x.weight) { Latest[x.y] = Latest[x.x] - x.weight; } } } // 找关键路径 for (int i = 0; i < N; i++) { for (auto e : rode[i]) { // e.y的最晚开始时间 - e.x的最早开始时间 - e.x->e.y的权重 // Delay 就是存的x节点和y节点之间的空余 // e是边x->y Delay.push_back({e, Latest[e.y] - Earliest[e.x] - e.weight}); } } for (auto e : Delay) { // 空余为0的关键路径 if (e.d == 0) { cout << e.e.x << "->" << e.e.y << " : " << e.e.weight << endl; } } return res; } int main() { cin >> N >> M; rode.resize(N + 5); Rrode.resize(N + 5); vis.resize(N + 5); Earliest.resize(N + 5); Latest.resize(N + 5); while (M--) { int x, y, d; cin >> x >> y >> d; rode[x].push_back({x, y, d}); Rrode[x].push_back({y, x, d}); } if (TopSort()) { for (auto e : topoOrder) { cout << e << ' '; } cout << endl; cout << CriticalPath(); } return 0; } /* 9 12 0 1 6 0 2 4 0 3 5 1 4 1 2 4 1 3 5 2 4 6 9 4 7 7 5 4 0 5 7 4 6 8 2 7 8 4 8 6 7 4 1 2 5 3 0 0->1 : 6 0->3 : 5 1->4 : 1 3->5 : 2 4->6 : 9 4->7 : 7 5->4 : 0 6->8 : 2 7->8 : 4 18 */
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。