📌  相关文章
📜  计算从源到目的地的所有可能的步行,恰好有 k 条边

📅  最后修改于: 2021-09-16 11:08:45             🧑  作者: Mango

给定一个有向图和其中的两个顶点 ‘u’ 和 ‘v’,计算从 ‘u’ 到 ‘v’ 的所有可能的步行,在步行上恰好有 k 条边。
该图被赋予邻接矩阵表示,其中 graph[i][j] 的值为 1 表示从顶点 i 到顶点 j 存在边,值为 0 表示从 i 到 j 没有边。

例如,考虑下图。让源’u’为顶点0,目的地’v’为3,k为2。输出应该是2,因为从0到3有两次步行,正好有2条边。行走是 {0, 2, 3} 和 {0, 1, 3}

图形

简单方法:创建一个递归函数,该函数采用当前顶点、目标顶点和顶点计数。以k的值为k-1的当前顶点的所有相邻顶点调用递归函数。当 k 的值为 0 时,则检查当前顶点是否为目的地。如果是目的地,则输出答案为 1。

下面是这个简单解决方案的实现。

C++
// C++ program to count walks from u to
// v with exactly k edges
#include 
using namespace std;
 
// Number of vertices in the graph
#define V 4
 
// A naive recursive function to count
// walks from u to v with k edges
int countwalks(int graph[][V], int u, int v, int k)
{
    // Base cases
    if (k == 0 && u == v)
        return 1;
    if (k == 1 && graph[u][v])
        return 1;
    if (k <= 0)
        return 0;
 
    // Initialize result
    int count = 0;
 
    // Go to all adjacents of u and recur
    for (int i = 0; i < V; i++)
        if (graph[u][i] == 1) // Check if is adjacent of u
            count += countwalks(graph, i, v, k - 1);
 
    return count;
}
 
// driver program to test above function
int main()
{
    /* Let us create the graph shown in above diagram*/
    int graph[V][V] = { { 0, 1, 1, 1 },
                        { 0, 0, 0, 1 },
                        { 0, 0, 0, 1 },
                        { 0, 0, 0, 0 } };
    int u = 0, v = 3, k = 2;
    cout << countwalks(graph, u, v, k);
    return 0;
}


Java
// Java program to count walks from u to v with exactly k edges
import java.util.*;
import java.lang.*;
import java.io.*;
 
class KPaths {
    static final int V = 4; // Number of vertices
 
    // A naive recursive function to count walks from u
    // to v with k edges
    int countwalks(int graph[][], int u, int v, int k)
    {
        // Base cases
        if (k == 0 && u == v)
            return 1;
        if (k == 1 && graph[u][v] == 1)
            return 1;
        if (k <= 0)
            return 0;
 
        // Initialize result
        int count = 0;
 
        // Go to all adjacents of u and recur
        for (int i = 0; i < V; i++)
            if (graph[u][i] == 1) // Check if is adjacent of u
                count += countwalks(graph, i, v, k - 1);
 
        return count;
    }
 
    // Driver method
    public static void main(String[] args) throws java.lang.Exception
    {
        /* Let us create the graph shown in above diagram*/
        int graph[][] = new int[][] { { 0, 1, 1, 1 },
                                      { 0, 0, 0, 1 },
                                      { 0, 0, 0, 1 },
                                      { 0, 0, 0, 0 } };
        int u = 0, v = 3, k = 2;
        KPaths p = new KPaths();
        System.out.println(p.countwalks(graph, u, v, k));
    }
} // Contributed by Aakash Hasija


Python3
# Python3 program to count walks from
# u to v with exactly k edges
 
# Number of vertices in the graph
V = 4
 
# A naive recursive function to count
# walks from u to v with k edges
def countwalks(graph, u, v, k):
 
    # Base cases
    if (k == 0 and u == v):
        return 1
    if (k == 1 and graph[u][v]):
        return 1
    if (k <= 0):
        return 0
     
    # Initialize result
    count = 0
     
    # Go to all adjacents of u and recur
    for i in range(0, V):
         
        # Check if is adjacent of u
        if (graph[u][i] == 1):
            count += countwalks(graph, i, v, k-1)
     
    return count
 
# Driver Code
 
# Let us create the graph shown in above diagram
graph = [[0, 1, 1, 1, ],
         [0, 0, 0, 1, ],
         [0, 0, 0, 1, ],
         [0, 0, 0, 0] ]
 
u = 0; v = 3; k = 2
print(countwalks(graph, u, v, k))
 
# This code is contributed by Smitha Dinesh Semwal.


C#
// C# program to count walks from u to
// v with exactly k edges
using System;
 
class GFG {
 
    // Number of vertices
    static int V = 4;
 
    // A naive recursive function to
    // count walks from u to v with
    // k edges
    static int countwalks(int[, ] graph, int u,
                          int v, int k)
    {
 
        // Base cases
        if (k == 0 && u == v)
            return 1;
        if (k == 1 && graph[u, v] == 1)
            return 1;
        if (k <= 0)
            return 0;
 
        // Initialize result
        int count = 0;
 
        // Go to all adjacents of u and recur
        for (int i = 0; i < V; i++)
 
            // Check if is adjacent of u
            if (graph[u, i] == 1)
                count += countwalks(graph, i, v, k - 1);
 
        return count;
    }
 
    // Driver method
    public static void Main()
    {
 
        /* Let us create the graph shown
        in above diagram*/
        int[, ] graph = new int[, ] { { 0, 1, 1, 1 },
                                      { 0, 0, 0, 1 },
                                      { 0, 0, 0, 1 },
                                      { 0, 0, 0, 0 } };
 
        int u = 0, v = 3, k = 2;
 
        Console.Write(
            countwalks(graph, u, v, k));
    }
}
 
// This code is contributed by nitin mittal.


PHP


Javascript


C++
// C++ program to count walks from
// u to v with exactly k edges
#include 
using namespace std;
 
// Number of vertices in the graph
#define V 4
 
// A Dynamic programming based function to count walks from u
// to v with k edges
int countwalks(int graph[][V], int u, int v, int k)
{
    // Table to be filled up using DP.
    // The value count[i][j][e] will
    // store count of possible walks from
    // i to j with exactly k edges
    int count[V][V][k + 1];
 
    // Loop for number of edges from 0 to k
    for (int e = 0; e <= k; e++) {
        for (int i = 0; i < V; i++) // for source
        {
            for (int j = 0; j < V; j++) // for destination
            {
                // initialize value
                count[i][j][e] = 0;
 
                // from base cases
                if (e == 0 && i == j)
                    count[i][j][e] = 1;
                if (e == 1 && graph[i][j])
                    count[i][j][e] = 1;
 
                // go to adjacent only when the
                // number of edges is more than 1
                if (e > 1) {
                    for (int a = 0; a < V; a++) // adjacent of source i
                        if (graph[i][a])
                            count[i][j][e] += count[a][j][e - 1];
                }
            }
        }
    }
    return count[u][v][k];
}
 
// driver program to test above function
int main()
{
    /* Let us create the graph shown in above diagram*/
    int graph[V][V] = { { 0, 1, 1, 1 },
                        { 0, 0, 0, 1 },
                        { 0, 0, 0, 1 },
                        { 0, 0, 0, 0 } };
    int u = 0, v = 3, k = 2;
    cout << countwalks(graph, u, v, k);
    return 0;
}


Java
// Java program to count walks from
// u to v with exactly k edges
import java.util.*;
import java.lang.*;
import java.io.*;
 
class KPaths {
    static final int V = 4; // Number of vertices
 
    // A Dynamic programming based function to count walks from u
    // to v with k edges
    int countwalks(int graph[][], int u, int v, int k)
    {
        // Table to be filled up using DP. The value count[i][j][e]
        // will/ store count of possible walks from i to j with
        // exactly k edges
        int count[][][] = new int[V][V][k + 1];
 
        // Loop for number of edges from 0 to k
        for (int e = 0; e <= k; e++) {
            for (int i = 0; i < V; i++) // for source
            {
                for (int j = 0; j < V; j++) // for destination
                {
                    // initialize value
                    count[i][j][e] = 0;
 
                    // from base cases
                    if (e == 0 && i == j)
                        count[i][j][e] = 1;
                    if (e == 1 && graph[i][j] != 0)
                        count[i][j][e] = 1;
 
                    // go to adjacent only when number of edges
                    // is more than 1
                    if (e > 1) {
                        for (int a = 0; a < V; a++) // adjacent of i
                            if (graph[i][a] != 0)
                                count[i][j][e] += count[a][j][e - 1];
                    }
                }
            }
        }
        return count[u][v][k];
    }
 
    // Driver method
    public static void main(String[] args) throws java.lang.Exception
    {
        /* Let us create the graph shown in above diagram*/
        int graph[][] = new int[][] { { 0, 1, 1, 1 },
                                      { 0, 0, 0, 1 },
                                      { 0, 0, 0, 1 },
                                      { 0, 0, 0, 0 } };
        int u = 0, v = 3, k = 2;
        KPaths p = new KPaths();
        System.out.println(p.countwalks(graph, u, v, k));
    }
} // Contributed by Aakash Hasija


Python3
# Python3 program to count walks from
# u to v with exactly k edges
 
# Number of vertices
V = 4
 
# A Dynamic programming based function
# to count walks from u to v with k edges
 
 
def countwalks(graph, u, v, k):
 
    # Table to be filled up using DP.
    # The value count[i][j][e] will/
    # store count of possible walks
    # from i to j with exactly k edges
    count = [[[0 for k in range(k + 1)]
              for i in range(V)]
             for j in range(V)]
 
    # Loop for number of edges from 0 to k
    for e in range(0, k + 1):
        # For Source
        for i in range(V):
            # For Desitination
            for j in range(V):
                # Initialize value
                # count[i][j][e] = 0
 
                # From base cases
                if (e == 0 and i == j):
                    count[i][j][e] = 1
                if (e == 1 and graph[i][j] != 0):
                    count[i][j][e] = 1
 
                # Go to adjacent only when number
                # of edges is more than 1
                if (e > 1):
 
                    for a in range(V):
 
                        # Adjacent of i
                        if (graph[i][a] != 0):
                            count[i][j][e] += count[a][j][e - 1]
 
    return count[u][v][k]
 
 
# Driver code
if __name__ == '__main__':
 
    # Let us create the graph shown
    # in above diagram
    graph = [[0, 1, 1, 1],
             [0, 0, 0, 1],
             [0, 0, 0, 1],
             [0, 0, 0, 0]]
 
    u = 0
    v = 3
    k = 2
 
    print(countwalks(graph, u, v, k))
 
# This code is contributed by Rajput-Ji


C#
// C# program to count walks from u to v
// with exactly k edges
using System;
 
class GFG {
    static int V = 4; // Number of vertices
 
    // A Dynamic programming based function
    // to count walks from u to v with k edges
    static int countwalks(int[, ] graph, int u,
                          int v, int k)
    {
        // Table to be filled up using DP. The
        // value count[i][j][e] will/ store
        // count of possible walks from i to
        // j with exactly k edges
        int[,, ] count = new int[V, V, k + 1];
 
        // Loop for number of edges from 0 to k
        for (int e = 0; e <= k; e++) {
 
            // for source
            for (int i = 0; i < V; i++) {
 
                // for destination
                for (int j = 0; j < V; j++) {
                    // initialize value
                    count[i, j, e] = 0;
 
                    // from base cases
                    if (e == 0 && i == j)
                        count[i, j, e] = 1;
                    if (e == 1 && graph[i, j] != 0)
                        count[i, j, e] = 1;
 
                    // go to adjacent only when
                    // number of edges
                    // is more than 1
                    if (e > 1) {
                        // adjacent of i
                        for (int a = 0; a < V; a++)
                            if (graph[i, a] != 0)
                                count[i, j, e] += count[a, j, e - 1];
                    }
                }
            }
        }
 
        return count[u, v, k];
    }
 
    // Driver method
    public static void Main()
    {
        /* Let us create the graph shown in
        above diagram*/
        int[, ] graph = { { 0, 1, 1, 1 },
                          { 0, 0, 0, 1 },
                          { 0, 0, 0, 1 },
                          { 0, 0, 0, 0 } };
        int u = 0, v = 3, k = 2;
 
        Console.WriteLine(
            countwalks(graph, u, v, k));
    }
}
 
// This is Code Contributed by anuj_67.


Javascript


输出:

2

复杂度分析:

  • 时间复杂度: O(V k )。
    上述函数的最坏情况时间复杂度为 O(V k ),其中 V 是给定图中的顶点数。我们可以通过绘制递归树来简单地分析时间复杂度。最坏的情况发生在完整的图上。在最坏的情况下,递归树的每个内部节点都恰好有 n 个子节点。
  • 辅助空间: O(V)。
    存储堆栈空间和访问数组需要 O(V) 空间。

有效的方法:可以使用动态规划来优化解决方案。这个想法是建立一个 3D 表,其中第一维是源,第二维是目的地,第三维是从源到目的地的边数,值是走的次数。与其他动态规划问题一样,以自下而上的方式填充 3D 表。

C++

// C++ program to count walks from
// u to v with exactly k edges
#include 
using namespace std;
 
// Number of vertices in the graph
#define V 4
 
// A Dynamic programming based function to count walks from u
// to v with k edges
int countwalks(int graph[][V], int u, int v, int k)
{
    // Table to be filled up using DP.
    // The value count[i][j][e] will
    // store count of possible walks from
    // i to j with exactly k edges
    int count[V][V][k + 1];
 
    // Loop for number of edges from 0 to k
    for (int e = 0; e <= k; e++) {
        for (int i = 0; i < V; i++) // for source
        {
            for (int j = 0; j < V; j++) // for destination
            {
                // initialize value
                count[i][j][e] = 0;
 
                // from base cases
                if (e == 0 && i == j)
                    count[i][j][e] = 1;
                if (e == 1 && graph[i][j])
                    count[i][j][e] = 1;
 
                // go to adjacent only when the
                // number of edges is more than 1
                if (e > 1) {
                    for (int a = 0; a < V; a++) // adjacent of source i
                        if (graph[i][a])
                            count[i][j][e] += count[a][j][e - 1];
                }
            }
        }
    }
    return count[u][v][k];
}
 
// driver program to test above function
int main()
{
    /* Let us create the graph shown in above diagram*/
    int graph[V][V] = { { 0, 1, 1, 1 },
                        { 0, 0, 0, 1 },
                        { 0, 0, 0, 1 },
                        { 0, 0, 0, 0 } };
    int u = 0, v = 3, k = 2;
    cout << countwalks(graph, u, v, k);
    return 0;
}

Java

// Java program to count walks from
// u to v with exactly k edges
import java.util.*;
import java.lang.*;
import java.io.*;
 
class KPaths {
    static final int V = 4; // Number of vertices
 
    // A Dynamic programming based function to count walks from u
    // to v with k edges
    int countwalks(int graph[][], int u, int v, int k)
    {
        // Table to be filled up using DP. The value count[i][j][e]
        // will/ store count of possible walks from i to j with
        // exactly k edges
        int count[][][] = new int[V][V][k + 1];
 
        // Loop for number of edges from 0 to k
        for (int e = 0; e <= k; e++) {
            for (int i = 0; i < V; i++) // for source
            {
                for (int j = 0; j < V; j++) // for destination
                {
                    // initialize value
                    count[i][j][e] = 0;
 
                    // from base cases
                    if (e == 0 && i == j)
                        count[i][j][e] = 1;
                    if (e == 1 && graph[i][j] != 0)
                        count[i][j][e] = 1;
 
                    // go to adjacent only when number of edges
                    // is more than 1
                    if (e > 1) {
                        for (int a = 0; a < V; a++) // adjacent of i
                            if (graph[i][a] != 0)
                                count[i][j][e] += count[a][j][e - 1];
                    }
                }
            }
        }
        return count[u][v][k];
    }
 
    // Driver method
    public static void main(String[] args) throws java.lang.Exception
    {
        /* Let us create the graph shown in above diagram*/
        int graph[][] = new int[][] { { 0, 1, 1, 1 },
                                      { 0, 0, 0, 1 },
                                      { 0, 0, 0, 1 },
                                      { 0, 0, 0, 0 } };
        int u = 0, v = 3, k = 2;
        KPaths p = new KPaths();
        System.out.println(p.countwalks(graph, u, v, k));
    }
} // Contributed by Aakash Hasija

蟒蛇3

# Python3 program to count walks from
# u to v with exactly k edges
 
# Number of vertices
V = 4
 
# A Dynamic programming based function
# to count walks from u to v with k edges
 
 
def countwalks(graph, u, v, k):
 
    # Table to be filled up using DP.
    # The value count[i][j][e] will/
    # store count of possible walks
    # from i to j with exactly k edges
    count = [[[0 for k in range(k + 1)]
              for i in range(V)]
             for j in range(V)]
 
    # Loop for number of edges from 0 to k
    for e in range(0, k + 1):
        # For Source
        for i in range(V):
            # For Desitination
            for j in range(V):
                # Initialize value
                # count[i][j][e] = 0
 
                # From base cases
                if (e == 0 and i == j):
                    count[i][j][e] = 1
                if (e == 1 and graph[i][j] != 0):
                    count[i][j][e] = 1
 
                # Go to adjacent only when number
                # of edges is more than 1
                if (e > 1):
 
                    for a in range(V):
 
                        # Adjacent of i
                        if (graph[i][a] != 0):
                            count[i][j][e] += count[a][j][e - 1]
 
    return count[u][v][k]
 
 
# Driver code
if __name__ == '__main__':
 
    # Let us create the graph shown
    # in above diagram
    graph = [[0, 1, 1, 1],
             [0, 0, 0, 1],
             [0, 0, 0, 1],
             [0, 0, 0, 0]]
 
    u = 0
    v = 3
    k = 2
 
    print(countwalks(graph, u, v, k))
 
# This code is contributed by Rajput-Ji

C#

// C# program to count walks from u to v
// with exactly k edges
using System;
 
class GFG {
    static int V = 4; // Number of vertices
 
    // A Dynamic programming based function
    // to count walks from u to v with k edges
    static int countwalks(int[, ] graph, int u,
                          int v, int k)
    {
        // Table to be filled up using DP. The
        // value count[i][j][e] will/ store
        // count of possible walks from i to
        // j with exactly k edges
        int[,, ] count = new int[V, V, k + 1];
 
        // Loop for number of edges from 0 to k
        for (int e = 0; e <= k; e++) {
 
            // for source
            for (int i = 0; i < V; i++) {
 
                // for destination
                for (int j = 0; j < V; j++) {
                    // initialize value
                    count[i, j, e] = 0;
 
                    // from base cases
                    if (e == 0 && i == j)
                        count[i, j, e] = 1;
                    if (e == 1 && graph[i, j] != 0)
                        count[i, j, e] = 1;
 
                    // go to adjacent only when
                    // number of edges
                    // is more than 1
                    if (e > 1) {
                        // adjacent of i
                        for (int a = 0; a < V; a++)
                            if (graph[i, a] != 0)
                                count[i, j, e] += count[a, j, e - 1];
                    }
                }
            }
        }
 
        return count[u, v, k];
    }
 
    // Driver method
    public static void Main()
    {
        /* Let us create the graph shown in
        above diagram*/
        int[, ] graph = { { 0, 1, 1, 1 },
                          { 0, 0, 0, 1 },
                          { 0, 0, 0, 1 },
                          { 0, 0, 0, 0 } };
        int u = 0, v = 3, k = 2;
 
        Console.WriteLine(
            countwalks(graph, u, v, k));
    }
}
 
// This is Code Contributed by anuj_67.

Javascript


输出:

2

复杂度分析:

  • 时间复杂度: O(V 3 )。
    填充DP表需要三个嵌套循环,所以时间复杂度为O(V 3/sup>)。
  • 辅助空间: O(V 3 )。
    存储DP表需要O(V 3 )空间。

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