📜  资质| GATE CS 1998 |问题25(1)

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

资质 | GATE CS 1998 | 问题25

本题是GATE CS 1998考试中的第25个问题,涉及到数据结构和算法问题。本题目的是要求程序员实现一个函数,在一个给定的有向无环图(DAG)中计算所有从源节点到目标节点的路径的总数。

问题描述

给定一个有向无环图(DAG)$G = (V, E)$,其中 $V$ 是节点集合,$E$ 是边集合。每个节点都由唯一的标识符 $id$ 表示。

假设我们有两个顶点 $s$ 和 $t$,分别表示图的起始节点和结束节点。现在要求实现一个函数 countPaths(Graph g, int s, int t),该函数计算从 $s$ 到 $t$ 的所有路径数量。如果不存在这样的路径,则函数应该返回 0。

输入格式

函数的输入参数是一个有向无环图 $g$,由适当的数据结构表示。每个节点都由唯一的标识符 $id$ 表示。此外,输入还包括起始节点 $s$ 和目标节点 $t$ 的标识符。

输出格式

函数应该输出从 $s$ 到 $t$ 的所有路径数量。如果不存在这样的路径,则函数应该返回 0。

算法思路

这是一道经典的动态规划问题。要计算从 $s$ 到 $t$ 的所有路径数量,我们可以定义一个长度为 $n$ 的数组 $count$,其中 $n$ 表示图中的节点数。对于任何节点 $u$,$count[u]$ 表示从 $u$ 到 $t$ 的所有路径数量。

现在我们考虑如何填充 $count$ 数组。为此,我们可以按照拓扑排序的顺序处理图中的所有节点。假设当前处理的节点是 $u$,那么我们可以遍历 $u$ 的所有直接后继 $v$,并为每个 $v$ 维护一个计数器 $count[v]$。我们可以将 $count[u]$ 的值更新为 $v$ 的计数器之和,即:

$$ count[u] = \sum\limits_{v \in succ(u)} count[v] $$

最终,当我们完成拓扑排序后,$count[s]$ 的值就是从 $s$ 到 $t$ 的所有路径数量。

代码实现

下面是一个Java代码片段实现了上述算法。

import java.util.*;

public class Graph {
    private int n;
    private List<Integer>[] adj;

    public Graph(int n) {
        this.n = n;
        adj = new List[n];
        for (int u = 0; u < n; u++) {
            adj[u] = new ArrayList<>();
        }
    }

    public void addEdge(int u, int v) {
        adj[u].add(v);
    }

    public int countPaths(int s, int t) {
        int[] count = new int[n];
        count[t] = 1;
        for (int u : topologicalSort()) {
            for (int v : adj[u]) {
                count[u] += count[v];
            }
        }
        return count[s];
    }

    private List<Integer> topologicalSort() {
        int[] inDegree = new int[n];
        for (int u = 0; u < n; u++) {
            for (int v : adj[u]) {
                inDegree[v]++;
            }
        }
        Queue<Integer> queue = new LinkedList<>();
        for (int u = 0; u < n; u++) {
            if (inDegree[u] == 0) {
                queue.offer(u);
            }
        }
        List<Integer> res = new ArrayList<>();
        while (!queue.isEmpty()) {
            int u = queue.poll();
            res.add(u);
            for (int v : adj[u]) {
                inDegree[v]--;
                if (inDegree[v] == 0) {
                    queue.offer(v);
                }
            }
        }
        return res;
    }
}