📌  相关文章
📜  有向无环图中从源到目的地的路径数

📅  最后修改于: 2021-09-22 10:10:41             🧑  作者: Mango

给定一个有 n 个顶点和 m 个边的有向无环图。任务是找到从源顶点到目标顶点存在的不同路径的数量。

例子:

方法:f(u) 是从节点 u 到目标顶点的路径数。因此, f(source) 是必需的答案。由于f(destination) = 1 ,所以从目的地到自身只有一条路径。可以观察到,f(u) 只依赖于所有可能从 u 出发的节点的 f 值。这是有道理的,因为从 u 到目的地的不同路径的数量是从v1、v2、v3…vn到目的地顶点的所有不同路径的总和,其中 v1 到 vn 是所有从顶点 u 有直接路径的顶点。然而,这种方法太慢而无用。每个函数调用分支为进一步的调用,然后分支为进一步的调用,直到每条路径都被探索一次。
这种方法的问题是每次使用参数 u 调用函数时都会一次又一次地计算 f(u)。由于这个问题同时表现出重叠子问题和最优子结构,因此动态规划适用于此。为了仅对每个 u 评估 f(u),在评估 f(u) 之前,对可以从 u 访问的所有 v 评估 f(v)。该条件通过图节点的反向拓扑排序顺序来满足。
下面是上述方法的实现:

CPP
// C++ program for Number of paths
// from one vertex to another vertex
//  in a Directed Acyclic Graph
#include 
using namespace std;
#define MAXN 1000005
 
// to make graph
vector v[MAXN];
 
// function to add edge in graph
void add_edge(int a, int b, int fre[])
{
    // there is path from a to b.
    v[a].push_back(b);
    fre[b]++;
}
 
// function to make topological sorting
vector topological_sorting(int fre[], int n)
{
    queue q;
 
    // insert all vertices which
    // don't have any parent.
    for (int i = 0; i < n; i++)
        if (!fre[i])
            q.push(i);
 
    vector l;
 
    // using kahn's algorithm
    // for topological sorting
    while (!q.empty()) {
        int u = q.front();
        q.pop();
 
        // insert front element of queue to vector
        l.push_back(u);
 
        // go through all it's childs
        for (int i = 0; i < v[u].size(); i++) {
            fre[v[u][i]]--;
 
            // whenever the freqency is zero then add
            // this vertex to queue.
            if (!fre[v[u][i]])
                q.push(v[u][i]);
        }
    }
    return l;
}
 
// Function that returns the number of paths
int numberofPaths(int source, int destination, int n, int fre[])
{
 
// make topological sorting
    vector s = topological_sorting(fre, n);
 
    // to store required answer.
    int dp[n] = { 0 };
 
    // answer from destination
    // to destination is 1.
    dp[destination] = 1;
 
    // traverse in reverse order
    for (int i = s.size() - 1; i >= 0; i--) {
        for (int j = 0; j < v[s[i]].size(); j++) {
            dp[s[i]] += dp[v[s[i]][j]];
        }
    }
 
    return dp;
}
 
// Driver code
int main()
{
 
    // here vertices are numbered from 0 to n-1.
    int n = 5;
    int source = 0, destination = 4;
 
    // to count number of vertex which don't
    // have any parents.
    int fre[n] = { 0 };
 
    // to add all edges of graph
    add_edge(0, 1, fre);
    add_edge(0, 2, fre);
    add_edge(0, 3, fre);
    add_edge(0, 4, fre);
    add_edge(2, 3, fre);
    add_edge(3, 4, fre);
 
    // Function that returns the number of paths
    cout << numberofPaths(source, destination, n, fre);
}


Python3
# Python3 program for Number of paths
# from one vertex to another vertex
# in a Directed Acyclic Graph
from collections import deque
MAXN = 1000005
 
# to make graph
v = [[] for i in range(MAXN)]
 
# function to add edge in graph
def add_edge(a, b, fre):
   
    # there is path from a to b.
    v[a].append(b)
    fre[b] += 1
 
# function to make topological sorting
def topological_sorting(fre, n):
    q = deque()
 
    # insert all vertices which
    # don't have any parent.
    for i in range(n):
        if (not fre[i]):
            q.append(i)
 
    l = []
 
    # using kahn's algorithm
    # for topological sorting
    while (len(q) > 0):
        u = q.popleft()
        #q.pop()
 
        # insert front element of queue to vector
        l.append(u)
 
        # go through all it's childs
        for i in range(len(v[u])):
            fre[v[u][i]] -= 1
 
            # whenever the freqency is zero then add
            # this vertex to queue.
            if (not fre[v[u][i]]):
                q.append(v[u][i])
    return l
 
# Function that returns the number of paths
def numberofPaths(source, destination, n, fre):
 
# make topological sorting
    s = topological_sorting(fre, n)
 
    # to store required answer.
    dp = [0]*n
 
    # answer from destination
    # to destination is 1.
    dp[destination] = 1
 
    # traverse in reverse order
    for i in range(len(s) - 1,-1,-1):
        for j in range(len(v[s[i]])):
            dp[s[i]] += dp[v[s[i]][j]]
    return dp
 
# Driver code
if __name__ == '__main__':
 
    # here vertices are numbered from 0 to n-1.
    n = 5
    source, destination = 0, 4
 
    # to count number of vertex which don't
    # have any parents.
    fre = [0]*n
 
    # to add all edges of graph
    add_edge(0, 1, fre)
    add_edge(0, 2, fre)
    add_edge(0, 3, fre)
    add_edge(0, 4, fre)
    add_edge(2, 3, fre)
    add_edge(3, 4, fre)
 
    # Function that returns the number of paths
    print (numberofPaths(source, destination, n, fre))
 
# This code is contributed by mohit kumar 29.


输出:
3

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程