给定一个有向加权图以及源和目标顶点。任务是找到从源到目的地,然后从目的地到源的路径上最短距离的总和,这样两条路径至少有一个公共顶点,而不是源和目的地。
注意:在从目标到源的过程中,所有边的方向都颠倒了。
例子:
Input: src = 0, des = 1
Output: 17
Explanation:
Common vertex is 4 and path is 0 -> 4 -> 3 -> 1 -> 4 -> 0
方法:想法是使用 Dijkstra 算法。在使用 Dijkstra 算法找到从源到目标的最短路径和从目标到源的最短路径时,它可能不会导致路径中除了源和目标顶点之外至少有一个节点是共同的。
- 让s是源顶点, d是目标顶点, v是从源到目标和目标到源的路径中共同的中间节点。最短的一对路径,所以 v 在这两条路径的交集是一条路径: s -> v -> d -> v -> s ,它的长度是
dis[s][v] + dis[v][d] + dis[d][v] + dis[v][s]
- 由于s和d是固定的,只需找到v使其给出最短路径。
- 为了找到这样的v ,请按照以下步骤操作:
- 找到从所有顶点到s和d 的最短距离,这为我们提供了dis[v][s]和dis[v][d] 的值。要找到从所有顶点到给定节点的最短路径,请参阅从所有顶点到目的地的最短路径。
- 从 s和d找到所有顶点的最短距离,这给了我们d[s][v]和d[d][v] 。
- 迭代所有v并找到d[s][v] + d[v][d] + d[d][v] + d[v][s] 的最小值。
下面是上述方法的实现:
CPP
// CPP implementation of the approach
#include
using namespace std;
#define INF 0x3f3f3f3f
// iPair represents the Integer Pair
typedef pair iPair;
// This class represents
// a directed graph using
// adjacency list representation
class Graph {
// Number of vertices
int V;
// In a weighted graph, store vertex
// and weight pair for every edge
list >* adj;
public:
// Constructor
Graph(int V);
// Function to add an edge to graph
void addEdge(int u, int v, int w);
// Find shortest path from
// source vertex to all vertex
void shortestPath(int src,
vector& dist);
};
// Allocates memory for adjacency list
Graph::Graph(int V)
{
this->V = V;
adj = new list[V];
}
// Function to add an edge to the graph
void Graph::addEdge(int u, int v, int w)
{
adj[v].push_back(make_pair(u, w));
}
// Function to find the shortest paths
// from source to all other vertices
void Graph::shortestPath(int src,
vector& dist)
{
// Create a priority queue to
// store vertices that
// are being preprocessed
priority_queue,
greater >
pq;
// Insert source itself in priority
// queue and initialize
// its distance as 0
pq.push(make_pair(0, src));
dist[src] = 0;
// Loop till priority queue
// becomes empty (or all
// distances are not finalized)
while (!pq.empty()) {
// The first vertex in pair
// is the minimum distance
// vertex, extract it from
// priority queue
int u = pq.top().second;
pq.pop();
// 'i' is used to get all
// adjacent vertices of a vertex
list >::iterator i;
for (i = adj[u].begin(); i != adj[u].end(); ++i) {
// Get vertex label and
// weight of current
// adjacent of u
int v = (*i).first;
int weight = (*i).second;
// If there is shorted
// path to v through u
if (dist[v] > dist[u] + weight) {
// Updating distance of v
dist[v] = dist[u] + weight;
pq.push(make_pair(dist[v], v));
}
}
}
}
// Function to return the
// required minimum path
int minPath(int V, int src, int des,
Graph g, Graph r)
{
// Create a vector for
// distances and
// initialize all distances
// as infinite (INF)
// To store distance of all
// vertex from source
vector dist(V, INF);
// To store distance of all
// vertex from destination
vector dist2(V, INF);
// To store distance of source
// from all vertex
vector dist3(V, INF);
// To store distance of
// destination from all vertex
vector dist4(V, INF);
// Computing shortest path from
// source vertex to all vertices
g.shortestPath(src, dist);
// Computing shortest path from
// destination vertex to all vertices
g.shortestPath(des, dist2);
// Computing shortest path from
// all the vertices to source
r.shortestPath(src, dist3);
// Computing shortest path from
// all the vertices to destination
r.shortestPath(des, dist4);
// Finding the intermediate node (IN)
// such that the distance of path
// src -> IN -> des -> IN -> src is minimum
// To store the shortest distance
int ans = INT_MAX;
for (int i = 0; i < V; i++) {
// Intermediate node should not be
// the source and destination
if (i != des && i != src)
ans = min(
ans,
dist[i] + dist2[i]
+ dist3[i] + dist4[i]);
}
// Return the minimum path required
return ans;
}
// Driver code
int main()
{
// Create the graph
int V = 5;
int src = 0, des = 1;
// To store the original graph
Graph g(V);
// To store the reverse graph
// and compute distance from all
// vertex to a particular vertex
Graph r(V);
// Adding edges
g.addEdge(0, 2, 1);
g.addEdge(0, 4, 5);
g.addEdge(1, 4, 1);
g.addEdge(2, 0, 10);
g.addEdge(2, 3, 5);
g.addEdge(3, 1, 1);
g.addEdge(4, 0, 5);
g.addEdge(4, 2, 100);
g.addEdge(4, 3, 5);
// Adding edges in reverse direction
r.addEdge(2, 0, 1);
r.addEdge(4, 0, 5);
r.addEdge(4, 1, 1);
r.addEdge(0, 2, 10);
r.addEdge(3, 2, 5);
r.addEdge(1, 3, 1);
r.addEdge(0, 4, 5);
r.addEdge(2, 4, 100);
r.addEdge(3, 4, 5);
cout << minPath(V, src, des, g, r);
return 0;
}
Python3
# Python implementation of the approach
from typing import List
from queue import PriorityQueue
from sys import maxsize as INT_MAX
INF = 0x3f3f3f3f
# This class represents
# a directed graph using
# adjacency list representation
class Graph:
def __init__(self, V: int) -> None:
# Number of vertices
self.V = V
# In a weighted graph, store vertex
# and weight pair for every edge
self.adj = [[] for _ in range(V)]
# Function to add an edge to the graph
def addEdge(self, u: int, v: int, w: int) -> None:
self.adj[v].append((u, w))
# Function to find the shortest paths
# from source to all other vertices
def shortestPath(self, src: int, dist: List[int]) -> None:
# Create a priority queue to
# store vertices that
# are being preprocessed
pq = PriorityQueue()
# Insert source itself in priority
# queue and initialize
# its distance as 0
pq.put((0, src))
dist[src] = 0
# Loop till priority queue
# becomes empty (or all
# distances are not finalized)
while not pq.empty():
# The first vertex in pair
# is the minimum distance
# vertex, extract it from
# priority queue
u = pq.get()[1]
# 'i' is used to get all
# adjacent vertices of a vertex
for i in self.adj[u]:
# Get vertex label and
# weight of current
# adjacent of u
v = i[0]
weight = i[1]
# If there is shorted
# path to v through u
if dist[v] > dist[u] + weight:
# Updating distance of v
dist[v] = dist[u] + weight
pq.put((dist[v], v))
# Function to return the
# required minimum path
def minPath(V: int, src: int, des: int, g: Graph, r: Graph) -> int:
# Create a vector for
# distances and
# initialize all distances
# as infinite (INF)
# To store distance of all
# vertex from source
dist = [INF for _ in range(V)]
# To store distance of all
# vertex from destination
dist2 = [INF for _ in range(V)]
# To store distance of source
# from all vertex
dist3 = [INF for _ in range(V)]
# To store distance of
# destination from all vertex
dist4 = [INF for _ in range(V)]
# Computing shortest path from
# source vertex to all vertices
g.shortestPath(src, dist)
# Computing shortest path from
# destination vertex to all vertices
g.shortestPath(des, dist2)
# Computing shortest path from
# all the vertices to source
r.shortestPath(src, dist3)
# Computing shortest path from
# all the vertices to destination
r.shortestPath(des, dist4)
# Finding the intermediate node (IN)
# such that the distance of path
# src -> IN -> des -> IN -> src is minimum
# To store the shortest distance
ans = INT_MAX
for i in range(V):
# Intermediate node should not be
# the source and destination
if (i != des and i != src):
ans = min(ans, dist[i] + dist2[i] + dist3[i] + dist4[i])
# Return the minimum path required
return ans
# Driver code
if __name__ == "__main__":
# Create the graph
V = 5
src = 0
des = 1
# To store the original graph
g = Graph(V)
# To store the reverse graph
# and compute distance from all
# vertex to a particular vertex
r = Graph(V)
# Adding edges
g.addEdge(0, 2, 1)
g.addEdge(0, 4, 5)
g.addEdge(1, 4, 1)
g.addEdge(2, 0, 10)
g.addEdge(2, 3, 5)
g.addEdge(3, 1, 1)
g.addEdge(4, 0, 5)
g.addEdge(4, 2, 100)
g.addEdge(4, 3, 5)
# Adding edges in reverse direction
r.addEdge(2, 0, 1)
r.addEdge(4, 0, 5)
r.addEdge(4, 1, 1)
r.addEdge(0, 2, 10)
r.addEdge(3, 2, 5)
r.addEdge(1, 3, 1)
r.addEdge(0, 4, 5)
r.addEdge(2, 4, 100)
r.addEdge(3, 4, 5)
print(minPath(V, src, des, g, r))
# This code is contributed by sanjeev2552
输出:
17
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。