📜  门| GATE CS 2012 |问题30(1)

📅  最后修改于: 2023-12-03 15:28:37.790000             🧑  作者: Mango

门 | GATE CS 2012 | 问题30

这是一道关于有向图的问题,考察了拓扑排序以及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。因此,实际上拓扑排序的方法更加适用于大规模图的求解。