/*
Supposing we're finding the second shortest path between 2 nodes A and B, start by finding the shortest path from A to all the other nodes using Dijkstra's algorithm. Do the same for node B.
Supposing the second shortest path can have the same length as the shortest path (a different edge), mark the edges of the shortest path found in the first Dijkstra. Now process the vertices used in the shortest path, for each one, try to use an edge, other than the one of the shortest path and check the distance from A to this vertex + weight of this edge + distance from this edge to B (using the values from the second Dijkstra).
*/
struct Edge {
int next, weight;
bool used;
Edge(int v = 0 , int w = 0) {
next= v, weight = w;
used = false;
}
};
vector<Edge> ugraph[MAX];
int distA[MAX], distB[MAX];
void dijkstraAlgorithm(int N, int s, int dist[MAX]) {
int i;
for (i = 0 ; i < N ; i++)
dist[i] = 100000000; // infinity
dist[s] = 0;
set<pair<int,int> > heap;
heap.insert(make_pair(0,s));
while (heap.size()) {
pair<int,int> cur = *heap.begin();
heap.erase( heap.begin());
int v = cur.second, d = -cur.first;
vector<Edge>::iterator it;
for ( it = ugraph[v].begin() ; it != ugraph[v].end(); it++) {
int tdist = d + it->weight;
if (tdist < dist[it->next] ) {
heap.erase( make_pair( -dist[it->next] , it->next ));
dist[it->next] = tdist;
heap.insert( make_pair( -tdist , it->next ));
}
}
}
}
void findSecondShortestPath(int N, int A, int B) {
dijkstraAlgorithm(N, A, distA);
dijkstraAlgorithm(N, B, distB);
int v = A, bestCost = distA[B];
vector<Edge>::iterator it;
vector<int> bestPath;
while (v != B) { // mark the shortest path
bestPath.push_back(v);
for ( it = ugraph[v].begin() ; it != ugraph[v].end(); it++)
if (distA[v] + it->weight + distB[ it->next ] == bestCost ) {
it->used = true;
v = it->next;
break;
}
}
int second = 100000000 , next, turningPoint,t;
v = A; // find the second best cost and identify the
while (v != B) { // turning point from the best path
for ( it = ugraph[v].begin() ; it != ugraph[v].end(); it++)
if (it->used == false) {
t = distA[v] + it->weight + distB[ it->next ];
if (second > t) {
second = t;
turningPoint = v;
}
}
else
next = it->next;
v = next;
}
printf("Second best = %d\n", second );
for (v = 0 ; bestPath[v] != turningPoint ; v++)
printf("%d ", bestPath[v]);
v = turningPoint;
printf("%d ", v); // print path
while (v != B) {
for ( it = ugraph[v].begin() ; it != ugraph[v].end(); it++)
if (distA[v] + it->weight + distB[ it->next ] == second ) {
printf("%d ", it->next);
v = it->next;
break;
}
}
putchar('\n');
}