📅  最后修改于: 2023-12-03 15:28:37.790000             🧑  作者: Mango
这是一道关于有向图的问题,考察了拓扑排序以及DFS的基本应用。
给定一个有向无环图,图中每个节点都有一定的初始加工时间。现在我们希望找到一条从start节点到end节点的路径,并在该路径上的所有节点中加工时间之和最小。
输入的第一行包含两个整数N和E,分别表示节点数和边数。
接下来E行,每行包含三个整数u,v和t,表示一条从u到v的边,需要的加工时间为t。
最后一行包含两个整数start和end,表示起点和终点。
输出一行整数,表示从start到end的最小加工时间和。
输入:
5 9
0 1 1
0 2 6
0 3 2
1 2 2
1 4 4
2 4 1
3 2 3
3 4 7
4 0 8
0 4
输出:
9
由于本题中的图是有向无环图,所以我们可以使用拓扑排序或DFS求解。这里我们介绍DFS的方法,主要的思想是利用DFS遍历图,并在递归返回的时候计算每条路径的加工时间和,最后比较所有路径的加工时间和,选取最短的路径。
具体来说,我们可以维护一个全局变量ans,表示当前的最小加工时间和。然后在遍历过程中,每次到达终点节点时,更新ans的值。当遍历完整个图后,ans的值就是起点到终点的最小加工时间和。
为了避免图中的环导致无限递归,我们需要维护一个状态数组visited,表示当前节点是否已经被访问过,遍历过程中只能访问未被访问过的节点。
#include <iostream>
#include <vector>
#include <cstring>
#define MAXN 10000
#define INF 0x3f3f3f3f
using namespace std;
int n, e;
vector<pair<int, int>> edges[MAXN];
int start, end, ans = INF;
bool visited[MAXN];
void dfs(int u, int time) {
if (u == end) { // 已到达终点
ans = min(ans, time); // 更新最小加工时间和
return;
}
visited[u] = true; // 标记节点已访问
for (auto& edge : edges[u]) {
int v = edge.first, t = edge.second;
if (!visited[v]) {
dfs(v, time + t); // 深度优先遍历
}
}
visited[u] = false; // 回溯,恢复节点的未访问状态
}
int main() {
cin >> n >> e;
for (int i = 0; i < e; i++) {
int u, v, t;
cin >> u >> v >> t;
edges[u].push_back({v, t});
}
cin >> start >> end;
memset(visited, false, sizeof(visited));
dfs(start, 0);
cout << ans << endl;
return 0;
}
以上就是本题的解题思路和代码实现。由于DFS涉及到递归,所以对于较大的图可能存在栈溢出的问题,需要使用栈的数据结构来实现非递归DFS。因此,实际上拓扑排序的方法更加适用于大规模图的求解。