非加权双向图中最短路径和第二最短路径的区别
- 最后更新: 2021年8月4日
给出一个包含N个节点和M条边的非加权双向图,用数组 arr[][2]表示。任务是找出从节点1到N的最短路径和第二最短路径的长度差。
注意:该图是连接的,不包含多条边和自循环。(2<=N<=20)
例子。
**输入。**N = 4, M = 4, arr[M][2]={{1, 2}, {2, 3}, {3, 4}, {1, 4}}} 。
**输出。**2
解释。 最短路径是1->4,第二条最短路径是1->2->3->4。 因此,差值是2。输入。 N = 6, M = 8, arr[M][2]={{1, 2}, {1, 3}, {2, 6}, {2, 3}, {2, 4}, {3, 4}, {3, 5}, {4, 6}} 。
**输出:**1
**办法。**其思路是深度优先搜索,找到所有可能的路径,并将其存储在向量中,对 向量 进行排序,找出最短路径和第二短路径的区别。按照下面的步骤来解决这个问题。
- 定义一个函数 dfs(vector<vector>& graph, int s, int e, vector vis, int count, vector& dp)并执行以下步骤。
- 初始化一个二维向量 graph[][],有N行,用来存储从每个顶点连接的顶点。
- 使用变量i在 [0, M]范围内迭代,并执行以下步骤。
- 初始化一个大小为N的向量vis[],以跟踪被访问的节点。
- 初始化一个向量**dp[]**来存储所有可能路径的长度。
- 调用函数**dfs(graph, 0, N-1, vis, 0, dp)**来寻找所有可能的路径,并将它们存储在向量 **dp[]**中。
- 将向量dp[]按升序排序。
- 如果向量 dp[]的大小大于1,则返回值dp[1]-dp[0]否则返回0作为答案。
下面是上述方法的实现。
C++14
// C++ program for the above approach#include <bits/stdc++.h>using namespace std;// DFS function to find all possible paths.void dfs(vector<vector<int> >& graph,int s,int e,vector<int> v,int count, vector<int>& dp){if (s == e) {// Push the number of nodes required for// one of the possible pathsdp.push_back(count);return;}for (auto i : graph[s]) {if (v[i] != 1) {// Mark the node as visited and// call the function to search for// possible paths and unmark the node.v[i] = 1;dfs(graph, i, e, v, count + 1, dp);v[i] = 0;}}}// Function to find the difference between the// shortest and second shortest pathvoid findDifference(int n,int m,int arr[][2]){// Construct the graphvector<vector<int> > graph(n, vector<int>());for (int i = 0; i < m; i++) {int a, b;a = arr[i][0];b = arr[i][1];graph[a - 1].push_back(b - 1);graph[b - 1].push_back(a - 1);}// Vector to mark the nodes as visited or not.vector<int> v(n, 0);// Vector to store the count of all possible paths.vector<int> dp;// Mark the starting node as visited.v[0] = 1;// Function to find all possible paths.dfs(graph, 0, n - 1, v, 0, dp);// Sort the vectorsort(dp.begin(), dp.end());// Print the differenceif (dp.size() != 1)cout << dp[1] - dp[0];elsecout << 0;}// Driver Codeint main(){int n, m;n = 6;m = 8;int arr[m][2]= { { 1, 2 }, { 1, 3 },{ 2, 6 }, { 2, 3 },{ 2, 4 }, { 3, 4 },{ 3, 5 }, { 4, 6 } };findDifference(n, m, arr);return 0;} |
输出
1
**时间复杂度。**O(2^N)
辅助空间。O(N)
高效的方法。利用第二条最短路径不可能包含所有与最短路径相同的边这一事实。将最短路径中的每条边逐一移除,继续寻找最短路径,那么其中一条必须是所需的第二最短路径。使用广度优先搜索来找到最佳解决方案。按照下面的步骤来解决这个问题。
- 定义一个函数get_edges(int s, vector& edges, vector p)并执行以下步骤。
- 定义一个函数**dist_helper(vector<vector > graph, vector& d, int v1, int v2, int N)**并执行以下步骤。
- 初始化向量**vis[]**以跟踪被访问的节点。
- 初始化一个成对的队列 q[],进行广度优先搜索并找到路径。
- 将 对 **{0, 0}**排入对 q[] 队列 。
- 将vis[0]的值标记为1(已访问)。
- 在一个while循环中迭代,直到对 q[] 的队列不是空的。
- 定义一个函数dist(vector<ctor > graph, vector& d, vector &p, int N)并执行以下步骤。
- 初始化一个二维向量 graph[][],有N个行,用来存储从每个顶点连接的顶点。
- 使用变量i在 [0, M]范围内进行迭代,并执行以下步骤。
- 初始化大小为N的向量p[]和d[],以跟踪父节点和路径的长度。
- 调用函数**dist(graph, d, p, N)**来寻找最短路径的长度。
- 初始化一个向量 **distances[]**来存储所有可能路径的长度。
- 将 **d[N-1]**的值推到 向量 distances[]中。
- 初始化一个向量**edges[]**以获得沿最短路径的所有边。
- 调用函数**get_edges(N-1, edges, p)**来寻找沿最短路径的所有边。
- 使用变量i在**[0, edges.size()-1]**范围内进行迭代,并执行以下步骤。
- 将向量distances**[**]按升序排序。
- 如果向量 distances[]的大小大于1,那么返回distances[1]-distances[0]的值,否则返回0作为答案。
下面是上述方法的实现。
C++
// C++ program for the above approach#include <bits/stdc++.h>using namespace std;// Function to get all the edges in// the shortest pathvoid get_edges(int s, vector<int>& edges, vector<int> p){if (s == -1)return;get_edges(p[s], edges, p);edges.push_back(s);}// Calculate the shortest distance// after removing an edge between// v1 and v2void dist_helper(vector<vector<int> > graph, vector<int>& d,int v1,int v2,int n){// Vector to mark the nodes visitedvector<int> v(n, 0);// For BFSqueue<pair<int,int> > q;q.push(make_pair(0, 0));v[0] = 1;// Iterate over the rangewhile (!q.empty()) {auto a = q.front();q.pop();for (int i : graph[a.first]) {if ((i == v1 && a.first == v2)|| (i == v2 && a.first == v1))continue;if (v[i] == 0) {d[i] = 1 + a.second;v[i] = 1;q.push(make_pair(i, d[i]));}}}}// Calculates the shortest distances and// maintain a parent arrayvoid dist(vector<vector<int> > graph, vector<int>& d,vector<int>& p,int n){// Vector to mark the nodes visitedvector<int> v(n, 0);// For BFSqueue<pair<int,int> > q;q.push(make_pair(0, 0));v[0] = 1;// Iterate over the rangewhile (!q.empty()) {auto a = q.front();q.pop();for (int i : graph[a.first]) {if (v[i] == 0) {p[i] = a.first;d[i] = 1 + a.second;v[i] = 1;q.push(make_pair(i, d[i]));}}}}// Function to find the difference between the// shortest and second shortest pathvoid findDifference(int n,int m,int arr[][2]){// Initializing and constructing the graphvector<vector<int> > graph(n, vector<int>());for (int i = 0; i < m; i++) {int a, b;a = arr[i][0];b = arr[i][1];graph[a - 1].push_back(b - 1);graph[b - 1].push_back(a - 1);}// Initializing the arraysvector<int> p(n, -1);vector<int> d(n, 1e9);// Calculate the shortest pathdist(graph, d, p, n);// Vector to store the lengths// of possible pathsvector<int> distances;distances.push_back(d[n - 1]);vector<int> edges;// Get all the edges along the shortest pathget_edges(n - 1, edges, p);// Iterate over the rangefor (int i = 0; i + 1 < edges.size(); i++) {// Calculate shortest distance after// removing the edgedist_helper(graph, d, edges[i], edges[i + 1], n);distances.push_back(d[n - 1]);}// Sort the paths in ascending ordersort(distances.begin(), distances.end());if (distances.size() == 1)cout << 0 << endl;elsecout << distances[1] - distances[0] << endl;}// Driver Codeint main(){int n, m;n = 6;m = 8;int arr[m][2]= { { 1, 2 }, { 1, 3 },{ 2, 6 }, { 2, 3 },{ 2, 4 }, { 3, 4 },{ 3, 5 }, { 4, 6 } };findDifference(n, m, arr);return 0;} |
输出
1
时间复杂度。 O(N*M)
辅助空间。O(N)
读者请注意!现在不要停止学习。掌握所有重要的DSA概念。 DSA自学课程以适合学生的价格掌握所有重要的DSA概念,并成为行业的准备者。 要完成从学习语言到DS Algo以及更多的准备工作,请参考 完整的面试准备课程.
如果你想参加专家的现场课程 ,请参考 面向在职人士的DSA现场课程 和 面向学生的竞争性编程直播.
我的个人笔记 箭头_下降_上升
保存