Special case in shortest path algorithm - algorithm

I have given a graph with V vertices, E edges, a source vertex s and a number m
The weight of each edge is equal to one
I have to find the shortest path to all those nodes whose distance from the source node is lesser than given number m
My approach:- I used Dijkstra algorithm and find a path for all nodes
and then selected those nodes whose distance is less than m but I am getting Time
limit exceed.
Is there any better approach or any algorithm anyone can suggest?
Update:-
I used BFS but still, I am getting TLE on some cases I am trying not to transverse all nodes rather than only those whose distance is less than m from source s and storing them in temp
Please correct me if my approach is wrong.
Here is my code
#include <bits/stdc++.h>
using namespace std;
const long long N = 5*1e4;
const long long W = 1e9;
const long long INF = 1e9;
vector<long long> g[N]; //graph
long long dist[N]; //distance
bool visited[N]; // is node visited or not
void shortest_path(long long s,long long m){
fill(dist, dist + N, INF);
fill(visited, visited + N, 0);
dist[s] = 0;
vector<int>temp;
queue<long long>q; //Queue
q.push(s);
while(!q.empty())
{
long long v = q.front();
q.pop();
if(visited[v]) continue;
visited[v] = 1;
temp.push_back(v); //storing nodes in temp
for(auto it: g[v])
{
long long u = it;
if(dist[v] + 1<= m) // nodes those distance is less than m
{
dist[u] = dist[v] + 1;
q.push(u);
}
}
}
for(int i=0;i<temp.size();i++){
cout<<temp[i]<<" ";
}
}
int main()
{
long long n;
cin>>n;
for(long long i = 0; i < n; ++i) g[i].clear();
for(long long i = 0; i < n-1; i++)
{
long long u,v;
cin>>u>>v;
u--;v--;
g[u].push_back(v);
g[v].push_back(u);
}
long long q;
cin>>q;
for(long long i=0;i<q;i++){
long long s,m;
cin>>s>>m;
s--;
shortest_path(s,m);
cout<<endl;
}
return 0;
}

Dijkstra's is just BFS that works on weighted graphs thanks to a priority queue, but if your graph is unweighted you can just use BFS

Related

minimum cost to reach destination through tunnels

Recently I faced a problem in the interview and not able to answer it. Any help will be appreciated.
Given a two dimensional grid (1 <= row <= 10^9 && 1 <= col <= 10^9) and starting and ending coordinates. we can only go to the four adjacent cells and it cost 1 unit. we also have N tunnels (1 <= N <= 200) whose starting and ending coordinates are given and if we go through the tunnel it costs k unit (1 <= k <= 10^9).
Note: It is not necessary to take tunnels but if we take one it costs k unit of energy per tunnel taken.
we have to find the minimum cost to reach the destination from the starting coordinate.
starting coordinate (1 <= sx, sy <= 10^9)
destination coordinate (1 <= fx, fy <= 10^9)
The problem needs to be transposed into a graph with a weight given to each vertex. Once we have done that, we can use the Dijkstra algorithm to find the shortest path.
Solving the problem thus boils down to transposing the problem into a graph with weighted vertices.
We can go from any cell to any other cell without going through a tunnel. The cost is then the manhattan distance. When the coordinate of a cell c1 is (x1,y1) and another cell c2 is (x2,y2), the manhattan distance between c1 and c2 is d=abs(x2-x1)+abs(y2-y1).
The nodes of the graph will correspond to the starting cell, the final cell, and every tunnel exit cells. The number of nodes in the graph is 2 + n where n is the number of tunnels.
There is a vertex between every node. The weight of a vertex to the final node is simply the manhattan distance. The weight of a vertex to a tunnel exit node is the manhattan distance to the tunnel entry cell plus the weight k associated to the tunnel.
This yields a graph that we can now solve using the Dijkstra algorithm to find the shortest path.
As chmike mentioned, the question can first be transformed into a graph. Then Djikstra's algorithm for finding shortest paths can be used. Here's is my code -
#include<bits/stdc++.h>
using namespace std;
#define int long long int
const int N = 402;
int dp[N][N];
pair<int,int> g[N];
int dist[N];
bool vis[N];
int32_t main(){
int k,a,b,c,d,n,p,q,r,s,index,nodes,val;
cin>>k>>a>>b>>c>>d>>n;
index = 2;
nodes = 2*n+1;
for(int i=1;i<=nodes;i++)
dist[i] = INT_MAX;
memset(vis,false,sizeof(vis));
memset(dp,-1,sizeof(dp));
for(int i=0;i<=nodes;i++)
dp[i][i] = 0;
g[0] = {a,b};
g[1] = {c,d};
dp[0][1] = dp[1][0] = abs(a-c)+abs(b-d);
for(int i=0;i<n;i++){
cin>>p>>q>>r>>s;
dp[index][index+1] = k;
dp[index+1][index] = k;
g[index] = {p,q};
g[index+1] = {r,s};
for(int j=0;j<index;j++){
val = abs(p-g[j].first)+abs(q-g[j].second);
dp[j][index] = dp[index][j] = val;
val = abs(r-g[j].first)+abs(s-g[j].second);
dp[j][index+1] = dp[index+1][j] = val;
}
index += 2;
}
for(int i=0;i<=nodes;i++){
int v = -1;
for(int j=0;j<=nodes;j++){
if(!vis[j] && (v == -1 || dist[j] < dist[v]))
v = j;
}
if(dist[v] == INT_MAX)
break;
vis[v] = true;
for(int j=0;j<=nodes;j++)
dist[j] = min(dist[j], dist[v]+dp[v][j]);
}
cout<<dist[1];
return 0;
}
you can use dynamic programming
#include <bits/stdc++.h>
using namespace std;
#define type long long
int main()
{ //k i sost of travelling through tunnel
//sx and sy are starting coordinates
//fx and fy are ending coordinates
//n are number of tunnels
int k, sx, sy, fx ,fy,n;
cin>>k>>sx>>sy>>fx>>fy>>n;
vector<vector<int>> arr(n, vector<int>(4,0));
map<pair<int, int> , pair<int,int>> mp;
//taking inputof tunnel elements and storing it in a map
for(int i=0; i<n; i++)
{
for(int j=0; j<4; j++)
cin>>arr[i][j];
pair<int,int> a,b;
a= pair<int,int> (arr[i][0], arr[i][1]);
b= pair<int, int> (arr[i][2], arr[i][3]);
mp[a] = b;
mp[b] =a;
}//cin the elements
//function
vector<vector<type>> dp (fx+1, vector<type>(fy+1,LONG_LONG_MAX));
dp[fx][fy] =0; //end
for(int i= fx; i>=0; i--)
{
for(int j= fy; j>=0; j--)
{
//go down
if(j+1< fy)
{
dp[i][j] = min(dp[i][j] , dp[i][j+1]+1 );
}
//go right
if(i+1< fx)
{
dp[i][j] = min(dp[i][j] , dp[i+1][j]+1 );
}
//tunnel
if(mp.find(pair<int, int> (i,j))!= mp.end())
{
pair<int, int> temp= mp[pair<int, int> (i,j)];
int a= temp.first, b= temp.second;
if(dp[a][b]!= LONG_LONG_MAX)
{
dp[i][j] = min(dp[i][j] , dp[a][b]+ k );
}
}
}
}//
cout<<dp[sx][sy]<<'\n';
}
here i have used dp
the array dp is 2-d matrix that saves the cost to reach fx, fy.
we start from bottom up approach, at each cell we find the minimum cost to reach the end.
we check the cost to reach by stepping 1 cell downward i.e. from dp[i][j] to dp[i][j+1] .
then we check the right cell by dp[i+1][j]
we see if tunnel is present.

Dijkstra's algorithm implementation for undirected cyclic graphs without priority queues

How can i implement the Dijkstra using only queues instead of priority queues
.Is this possible ? if not,why ? This is My Code in java.. whats my mistake ?
"S" is the starting node "W" is the weight "N" is the size of the matrix. I added 1 to the length of the adj matrix since the first node is "1".
This is a problem from HackerRank Link :https://www.hackerrank.com/challenges/dijkstrashortreach
import java.io.*;
import java.util.*;
public class Solution {
public static void main(String[] args) {
Scanner in = new Scanner (System.in);
int cases = in.nextInt();
for(int i=0; i<cases; i++){
int N = in.nextInt();
int M = in.nextInt();
int adj[][] = new int[N+1][N+1];
for(int j=0; j<N+1; j++){
for(int k=0; k<N+1; k++){
adj[j][k] = 0;
}
}
for(int j=0; j<M; j++){
int A = in.nextInt();
int B = in.nextInt();
int W = in.nextInt();
adj[A][B] = W;
adj[B][A] = W;
}
int S = in.nextInt();
Queue<Integer> que = new LinkedList<Integer>();
que.add(S);
int dist[] = new int[N+1];
Arrays.fill(dist,Integer.MAX_VALUE);
boolean vis[] = new boolean[N+1];
dist[S] = 0;
vis[S] = true;
while(!que.isEmpty()){
int q = que.poll();
for(int j=1; j<=N; j++){
if(!vis[j]&&q!=j && adj[q][j]!=0){
if(dist[j]>dist[q]+adj[q][j]){
dist[j] = dist[q]+adj[q][j];
que.add(j);
}
}
}
vis[q] = true;
}
for(int j=1; j<=N; j++){
if(dist[j]!=0)
System.out.print(dist[j]+" ");
}
}
}
}
Yes, it is possible to implement it like that but it's less than optimal.
Because you use queues instead of priority queues you may have to expand the same portion of the graph multiple times. Because of that you replace the logN with something like N^2 (if i'm not mistaking).
If you don't expand a node multiple times (like you do in your code) then it's wrong because you use a cost that is higher than the minimum. Imagine that you have 2 nodes with a direct link of cost 20 or an indirect link through a third node with cost 1 on both edges. You would expact the second node assuming minimum distance is 20 (because it arrived first in the queue) but if you waited you would find a path with cost 2. Add more nodes to the indirect path if this is not already obvious.
At least do a linear search to find the minimum to bring it back to N (overall complexity O(N^2) with your setup). The best implementation has complexity O((N+M)logN).
Another mistake in your code is in reading the data:
for(int j=0; j<M; j++){
int A = in.nextInt();
int B = in.nextInt();
int W = in.nextInt();
adj[A][B] = W;
adj[B][A] = W;
}
According to the problem statement you can have multiple edges between two nodes. You only use the last one. Switch to take the minimum and you should be good.

Time Complexity O(V^3) or O(V^2)?

I'm new for analyzing the algorithms and the time for them.. This algorithm is posted in http://geeksforgeeks.com and they wrote that the time complexity of the algorithm is O(V^2) which i think that it's O(V^3):
int minDistance(int dist[], bool sptSet[])
{
// Initialize min value
int min = INT_MAX, min_index;
for (int v = 0; v < V; v++)
if (sptSet[v] == false && dist[v] <= min)
min = dist[v], min_index = v;
return min_index;
}
// A utility function to print the constructed distance array
int printSolution(int dist[], int n)
{
printf("Vertex Distance from Source\n");
for (int i = 0; i < V; i++)
printf("%d \t\t %d\n", i, dist[i]);
}
// Funtion that implements Dijkstra's single source shortest path algorithm
// for a graph represented using adjacency matrix representation
void dijkstra(int graph[V][V], int src)
{
int dist[V]; // The output array. dist[i] will hold the shortest
// distance from src to i
bool sptSet[V]; // sptSet[i] will true if vertex i is included in shortest
// path tree or shortest distance from src to i is finalized
// Initialize all distances as INFINITE and stpSet[] as false
for (int i = 0; i < V; i++)
dist[i] = INT_MAX, sptSet[i] = false;
// Distance of source vertex from itself is always 0
dist[src] = 0;
// Find shortest path for all vertices
for (int count = 0; count < V-1; count++)
{
// Pick the minimum distance vertex from the set of vertices not
// yet processed. u is always equal to src in first iteration.
int u = minDistance(dist, sptSet);
// Mark the picked vertex as processed
sptSet[u] = true;
// Update dist value of the adjacent vertices of the picked vertex.
for (int v = 0; v < V; v++)
// Update dist[v] only if is not in sptSet, there is an edge from
// u to v, and total weight of path from src to v through u is
// smaller than current value of dist[v]
if (!sptSet[v] && graph[u][v] && dist[u] != INT_MAX
&& dist[u]+graph[u][v] < dist[v])
dist[v] = dist[u] + graph[u][v];
}
// print the constructed distance array
printSolution(dist, V);
}
Where the graph represented inside graph[][] (matrix representation).
Thanks in advance
The solution is indeed O(V^2):
for (int i = 0; i < V; i++)
dist[i] = INT_MAX, sptSet[i] = false;
This part runs BEFORE the main loop, and in complexity of O(V) -.
for (int count = 0; count < V-1; count++)
{
This is the main loop, it runs O(V) times overall, and each time it requires:
int u = minDistance(dist, sptSet);
This runs one time per each different value of count, and its complexity is O(V), so we have O(V^2)` by now.
sptSet[u] = true;
This is O(1), and runs O(V) times.
for (int v = 0; v < V; v++)
This loop runs O(V) times, for each value of count, let's examine what happens each time you run it:
if (!sptSet[v] && graph[u][v] && dist[u] != INT_MAX
&& dist[u]+graph[u][v] < dist[v])
dist[v] = dist[u] + graph[u][v];
All of those are O(1), and done per each (count,v) pair, and there are O(V^2) of those pairs.
So, totally O(V^2).
Note that for more efficient graph representation, we can run Dijkstra's algorithm in O(E + VlogV), which might be better in case of sparse graphs.

Calculate Number of path between two nodes

Kingdom Connectivity
It has been a prosperous year for King Charles and he is rapidly expanding his kingdom.A beautiful new kingdom has been recently constructed and in this kingdom there are many cities connected by a number of one-way roads.Two cities may be directly connected by more than one roads, this is to ensure high connectivity.
In this new kingdom King Charles has made one of the cities at his financial capital and one as warfare capital and he wants high connectivity between these two capitals.The connectivity of a pair of cities say city A and city B is defined as the number of different paths from city A to city B. A path may use a road more than once if possible. Two paths are considered different if they do not use exactly the same sequence of roads.
There are N cities numbered 1 to N in the new kingdom and M one-way roads . City 1 is the monetary capital and city N is the warfare capital.
You being one of the best programmers in new kingdom need to answer the connectivity of financial capital and warfare capital ,i.e number of different paths from city 1 to city N.
Input Description:
First line contains two integers N and M.
Then follow M lines ,each having two integers say x and y, 1<=x,y<=N , indicating there is a road from city x to city y.
Output Description:
Print the number of different paths from city 1 to city N modulo 1,000,000,000(10^9).If there are infinitely many different paths print "INFINITE PATHS"(quotes are for clarity).
Sample Input:
5 5
1 2
2 4
2 3
3 4
4 5
Sample Output:
2
Sample Input:
5 5
1 2
4 2
2 3
3 4
4 5
Sample Output:
INFINITE PATHS
Constraints:
2<=N<=10,000(10^4)
1<=M<=1,00,000(10^5)
Two cities may be connected by more than two roads and in that case those roads are to be considered different for counting distinct paths
The algorithm that i use to solve the problem is :
Detect if the node n is reachable from node 1.
Its its not then the required ans is 0
If its reachable then find if there is any cycle in the graph by doing dfs from node 0
If there is a cycle then print INFINITE PATHS
If there is no cycle calculate the required ans using the recurrence
F(n) = 1
F(0) = Sumofall F(x) such that x is adjacent to 0
F(x) = 0 if there is no x adjacent to x
I have implemented the solution as :
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
vector<vector<pair<int, int> > > g;
int seen[10001] = {0};
int colour[10001] = {0};
bool has_cycle(int u) {
colour[u] = 1;
for(int i = 0; i < g[u].size(); i++) {
if(colour[g[u][i].first]==1) return true;
if(!colour[g[u][i].first])
if(has_cycle(g[u][i].first)) return true;
}
colour[u] = 2;
return false;
}
bool reachable(int u, int v) {
if(u==v) return true;
seen[u] = true;
for(int i = 0; i < g[u].size(); i++) {
if(!seen[g[u][i].first]) {
if(reachable(g[u][i].first, v)) return true;
}
}
return false;
}
long long mm[10001] = {0};
long long solve(int u, int n) {
if(u==n) return mm[u]=1;
if(mm[u]!=-2) return mm[u];
long long ans = 0;
for(int i = 0; i < g[u].size(); i++) {
ans += ((g[u][i].second%1000000000)*(solve(g[u][i].first, n)%1000000000)%1000000000);
ans %= 1000000000;
}
return mm[u]=ans;
}
long edge[100001];
int main() {
int n, m;
scanf("%d%d", &n, &m);
g.resize(n);
for(int i = 0; i < m; i++) {
int x, y;
scanf("%d%d", &x, &y);
x--; y--;
edge[i] = x*100000+y;
}
sort(edge, edge+m);
edge[m] = -1;
int last = edge[0];
int cnt = 1;
for(int i = 1; i <= m; i++) {
if(edge[i]!=last || i==m) {
int u, v;
u = last/100000;
v = last%100000;
if(i!=0) {
g[u].push_back(make_pair(v, cnt));
}
cnt = 1;
} else {
cnt++;
}
last = edge[i];
}
for(int i = 0; i < n; i++) mm[i] = -2;
if(reachable(0, n-1)) {
if(has_cycle(0)) printf("INFINITE PATHS\n");
else
printf("%lld\n", solve(0, n-1)%1000000000);
} else printf("0\n");
}
I am not able to detect the problem with this algorithm
Number (3)+(4) are wrong:
If its reachable then find if there is any cycle in the graph by
doing dfs from node 0.
If there is a cycle then print INFINITE PATHS
There could be a cycle in the graph, but the required #paths would still be a finite number, if the target is not reachable from the cycle.
Example: Looking for #paths from A to C
A-->D<-->B
|
----->C
In here: G=(V,E), V = {A,B,C,D} and E = {(D,B),(B,D),(A,C),(A,D)}
Though there is a cycle reachable from A (A->D->B->D), there is only one path from A to C.
To find if there are cycles in a path leading from source to target one can create a new graph G'=(V',E'), where V'= { v | there is a path in the original graph from v to target }, and E' = V' x V' [intersection] E (E reduced only to the vertices of V'), and run DFS/BFS on G'.
Also note, that if there are no cycles in G' - it is a DAG by definition, so working on G' from now on, will probably simplify also finding the #paths. (You will also have to trim vertices that are not reachable from source to make sure it is indeed a DAG).
Obvious mistake. Suppose that there is a cycle, but there is no path from the cycle to the second city. Then you will say that there are an infinite number of paths, but the number of paths may actually be finite.
You can reference my code
#include <iostream>
#include <vector>
#include <set>
#include <stack>
#include <map>
#include <algorithm>
#include <iomanip>
#include <numeric>
#include "string.h"
#define MODE 1000000000
using namespace std;
int main () {
vector<int> adj[10001], inv_adj[10001];
int indegree[10001];
int visited[10001];
int ranks[10001];
long long total[10001];
int N, M;
cin >> N >> M;
memset(indegree, 0, (N+1)*sizeof(int));
adj[0].push_back(1);
inv_adj[1].push_back(0);
indegree[1] = 1;
for (int i=0;i<M;i++)
{
int s, t;
cin >> s >> t;
adj[s].push_back(t);
inv_adj[t].push_back(s);
indegree[t]++;
}
stack<int> st;
st.push(0);
memset(visited, 0, (N+1)*sizeof(int));
visited[0] = 1;
while (!st.empty()) {
int v = st.top();
st.pop();
for (int i=0;i<adj[v].size();i++)
if (!visited[adj[v][i]])
{
st.push(adj[v][i]);
visited[adj[v][i]] = 1;
}
}
if(!visited[N])
{
cout << 0 << endl;
return 0;
}
for (int i=1;i<=N;i++)
{
if(!visited[i]){
for (int j=0;j<adj[i].size();j++)
indegree[adj[i][j]]--;
}
}
int count = 0;
stack<int> topo;
for (int i=0;i<=N;i++)
{
int j;
for (j=0;j<=N;j++)
if (visited[j] && indegree[j] ==0)
break;
if (j > N)
{
cout << "INFINITE PATHS" << endl;
return 0;
}
else
{
topo.push(j);
ranks[count++] = j;
if (j == N)
break;
indegree[j] = -1;
for (int k=0;k<adj[j].size();k++)
indegree[adj[j][k]]--;
}
}
memset(total, 0, (N+1)*sizeof(long long));
total[N] = 1;
for (int i=count - 1;i>=0;i--)
{
int r = ranks[i];
for (int j=0;j<inv_adj[r].size();j++)
if(visited[inv_adj[r][j]])
{
total[inv_adj[r][j]] = (total[inv_adj[r][j]] + total[r]) % MODE;
}
}
cout << total[0] << endl;
return 0;
}

Find all possible Euler cycles

I have implemented an algorithm to find an Euler cycle for a given starting vertex in an undirected graph (using DFS and removing visited edges), but it always returns only one path. How do I modify the algorithm to search for all possible Euler cycles for a vertex?
Here is relevant code:
typedef int Graph[200][200]; // adjacency matrix
int v, e; // vertex count, edge count
......
void DFS(Graph &G, int x) {
int i;
Push(x);
for (i = 0; i < v; i++)
if (G[i][x] > 0) {
G[i][x] = 0;
G[x][i] = 0;
DFS(G, i);
break;
}
}
After the recursive call, you should reinsert the edges you deleted before, and get rid of the break.
void DFS(Graph &G, int x)
{
int i;
Push(x);
for (i = 0; i < v; i++)
if (G[i][x] > 0)
{
G[i][x] *= -1;
G[x][i] *= -1;
DFS(G, i);
G[i][x] *= -1;
G[x][i] *= -1;
}
}
All you need now is a way to figure out when you've generated a full cycle so you can print it and move on to the next. That happens when you've eliminated every edge of your graph.
You want to loop through all vertex.

Resources