There are N network nodes, labelled 1 to N.
Given times, a list of travel times as directed edges times[i] = (u, v, w), where u is the source node, v is the target node, and w is the time it takes for a signal to travel from source to target.
Now, we send a signal from a certain node K. How long will it take for all nodes to receive the signal? If it is impossible, return -1.
here is my code.. however it is giving wrong answer
class Solution {
public:
int networkDelayTime(vector <vector<int>> ×, int N, int K) {
vector<int> time(N + 1);
vector<int> visited(N + 1, 0);
vector < vector < pair < int, int >> > graph(N + 1);
for (int i = 0; i < times.size(); i++) {
graph[times[i][0]].push_back(make_pair(times[i][1], times[i][2]));
}
queue <pair<int, int>> q;
q.push(make_pair(K, 0));
visited[K] = 1;
time[K] = 0;
while (!q.empty()) {
int end = q.front().first;
int duration = q.front().second;
q.pop();
for (auto k:graph[end]) {
int first = k.first;
int second = k.second;
if (!visited[first]) {
q.push(make_pair(first, second));
time[first] = duration + second;
visited[first] = 1;
} else {
time[first] = min(time[first], (duration + second));
}
}
}
for (int i = 1; i <= N; i++) {
if (visited[i] == 0) {
return -1;
}
}
sort(time.begin(), time.end());
return time[N];
}
};
I am not able to figure out where I am wrong.
Thanks
This is a text-book application of Dijkstra's algorithm.
Given a node K, this algorithm will fill an array with the minimum distance from K to every other node, so the biggest value in this array will be the total time it takes for the signal to reach every other node.
You can't just use a BFS because it won't necessarily consider a shorter path to a node once it has already found any other path to that node. Dijkstra's algorithm is a modification of the BFS that deals with that. See this example, supposing the initial node is 1, the distances to the other nodes given by BFS and Dijkstra are different:
Related
I'm creating a graph taking a file as input and I want to calculate the shortest path, to do so I used SPF algorithm. I have a few file I can use to see if it works, and here comes the problem because it works until I try it with the biggest one (which has over 1 million vertex and 2 million edges), considering that the second for dimension has about 700k vertex and 100 million edges and with it it works just fine, what do you think the problem is? I just need some hint I really can't figure it out!
Please be patient with me, I'm new in this comunity and to coding in general, I'm just trying to learn and understand things properly...
It's returning error 3221225725
// Function to compute the SPF algorithm
void shortestPathFaster(int S, int V)
{
// Create array d to store shortest distance
int d[V + 1];
// Boolean array to check if vertex
// is present in queue or not
bool inQueue[V + 1] = { false };
// Initialize the distance from source to
// other vertex as INT_MAX(infinite)
for (int i = 0; i <= V; i++) {
d[i] = INT_MAX;
}
d[S] = 0;
queue<int> q;
q.push(S);
inQueue[S] = true;
while (!q.empty()) {
// Take the front vertex from Queue
int u = q.front();
q.pop();
inQueue[u] = false;
// Relaxing all the adjacent edges of
// vertex taken from the Queue
for (int i = 0; i < graph[u].size(); i++) {
int v = graph[u][i].first;
int weight = graph[u][i].second;
if (d[v] > d[u] + weight) {
d[v] = d[u] + weight;
// Check if vertex v is in Queue or not
// if not then push it into the Queue
if (!inQueue[v]) {
q.push(v);
inQueue[v] = true;
}
}
}
}
// Print the result
print_distance(d, V);
}
The problem is most likely here:
int d[V + 1];
Firstly, variable length arrays are non-standard. Secondly, if V is large you will overflow the stack.
Solution: replace this with std::vector. bool inQueue[V + 1] should be treated similarly.
Also, replace char buffer[BUFFER_SIZE]; with std::string. You'll be glad you did.
I have tried to solve the problem Rerouting at hacker rank. I am posting here for help as competition is over.
https://www.hackerrank.com/contests/hack-the-interview-v-asia-pacific/challenges/rerouting
I have tried to solve problem using Strong connected components, but test cases failed. I can understand we have to remove cycles. But I stuck how to approach problem. Below is solution i have written. I am looking for guidence how to move forward so that i can apply my knowledge future based on mistakes i made here. Thanks for your time and help
int getMinConnectionChange(vector<int> connection) {
// Idea: Get number of strongly connected components.
int numberOfVertices = connection.size();
for(int idx = 0; idx < numberOfVertices; idx++) {
cout << idx+1 <<":"<< connection[idx] << endl;
}
stack<int> stkVertices;
map<int, bool> mpVertexVisited; //is vertex visited.think this as a chalk mark for nodes visited.
int numOFSCCs = 0;
int currTime = 1;
for (int vertexId = 0; vertexId < numberOfVertices; vertexId++) {
// check if node is already visited.
if (mpVertexVisited.find(vertexId+1) == mpVertexVisited.end()) {
numOFSCCs++;
mpVertexVisited.insert(make_pair(vertexId+1, true));
stkVertices.push(vertexId+1);
currTime++;
while (!stkVertices.empty()) {
int iCurrentVertex = stkVertices.top();
stkVertices.pop();
// get adjacent vertices. In this excercise we have only one neighbour. i.e., edge
int neighbourVertexId = connection[iCurrentVertex-1];
// if vertex is already visisted, don't insert in to stack.
if (mpVertexVisited.find(neighbourVertexId) != mpVertexVisited.end()) {
continue;
}
mpVertexVisited.insert(make_pair(neighbourVertexId, true));
stkVertices.push(neighbourVertexId);
} // while loop
} // if condition m_mapVrtxTimes.find(*itr) == m_mapVrtxTimes.end()
} // for loop of vertices
return numOFSCCs - 1;
}
This is a problem that I just solved and would like to share the solution.
The problem can be solved with union-find.
Two main observation:
The number of edges that has to be changed is the number of components - 1 (not necessarily strongly connected) Thus, union-find is handy here for finding the number of components
Second observation is that some component doesn't have terminating node, consider 1<->2, in other words, a cycle exist. We can detect whether there exists a terminating node if some node doesn't have an outgoing edge.
If all components have a cycle, it means that we need to change every component instead of a number of components - 1. This is to make it such that the graph will have a terminating point.
Code:
struct UF {
vector<int> p, rank, size;
int cnt;
UF(int N) {
p = rank = size = vector<int>(N, 1);
for (int i = 0; i < N; i++) p[i] = i;
cnt = N;
}
int find(int i) {
return p[i] == i ? i : p[i] = find(p[i]);
}
bool connected(int i, int j) {
return find(i) == find(j);
}
void join(int i, int j) {
if (connected(i, j)) return;
int x = find(i), y = find(j);
cnt--;
if (rank[x] > rank[y]) {
p[y] = x;
size[x] += size[y];
} else {
p[x] = y;
size[y] += size[x];
if (rank[x] == rank[y]) rank[y]++;
}
}
};
int getMinConnectionChange(vector<int> connection) {
int nonCycle = 0;
int n = connection.size();
UF uf(n);
for(int i=0;i<n;i++) {
int to = connection[i] - 1;
if(to == i) nonCycle++;
else uf.join(i, to);
}
int components = uf.cnt;
int countCycle = uf.cnt - nonCycle;
int res = components - 1;
if(countCycle == components) res++; // all components have cycle
return res;
}
TL;DR: you can view this as looking for a minimal spanning arborescence problem.
More precisely, add a node for each server, and another one called "Terminate".
Make a complete graph (each node is linked to every other one) and set as cost 0 for the edges corresponding to your input, 1 for the other ones.
You can use for example Edmond's algorithm to solve this.
We have n vertices (where n is less than 100 000) and m random edges (where m is less than 10 000 000). We want to find a path between 2 given vertices. If there is no path we will just print -1.
My algorithm is to build a tree. Every vertex has a disjoint_index (i) which shows that all vertices with disjoint_index (i), are connected.
The default value of disjoint_index is the index of each vertex. After finding an edge between vertex v and u, I check if they are connected. If they are connected, I do nothing. Else I change the disjoint_index of u and all the vertices connected to u by a function named (dfs).
Here is the code of the function to build this tree in c++:
struct vertex{
int disjoint_index;
vector<int> adjacent;
};
void build_tree(int m, int s, int e)
{
for(int i = 0; i < m; i++)
{
int u = kiss() % n;
int v = kiss() % n;
if(disjoint_counter[u] > disjoint_counter[v])
{
int temp = u;
u = v;
v = temp;
}//counter v > u
if(ver[v].disjoint_index != ver[u].disjoint_index)
{
ver[v].adjacent.push_back(u);
ver[u].adjacent.push_back(v);
dfs(v, u, ver[v].disjoint_index);
disjoint_counter[v] += disjoint_counter[u];
}
if(ver[s].disjoint_index == ver[e].disjoint_index)
return;
}
}
void dfs(int parent, int v, int d)
{
ver[v].disjoint_index = d;
for(int i = 0; i < ver[v].adjacent.size(); i++)
{
if(ver[v].adjacent[i] == parent)
continue;
dfs(v, ver[v].adjacent[i], d);
}
}
Here you can skip kiss, It's just a function that returns two vertices and shows that there is an edge between u and v.
disjoint_counter[i] shows how many vertices are in connected group i.
After building this tree I will find a path with a simple dfs. The time limit is 1s and I get Time Limit Exceeded on some test cases.
Edit: Memory is limited so I can't save all the edges.
Maximum memory I can use is 32MB.
I used the disjoint set union algorithm, it developed speed.
This is an interviewbit.com problem : https://www.interviewbit.com/problems/largest-distance-between-nodes-of-a-tree/
Given an arbitrary unweighted rooted tree which consists of N (2 <= N <= 40000) nodes. The goal of the problem is to find largest distance between two nodes in a tree. Distance between two nodes is a number of edges on a path between the nodes (there will be a unique path between any pair of nodes since it is a tree). The nodes will be numbered 0 through N - 1.
I am finding a node which is farthest from root node using dfs. From this node i am doing DFS to find the farthest node. this distance is the required answer. I implemented it, but while calling do_dfs function i am getting segmentation fault. i wrote return statement after every line to find out where i am getting error. I have indicated that line in comment in code.
pair<int,int> do_dfs(vector<vector<int>> &adj, int n, int root)
{
int l1 = 0;
stack<pair<int,int>> st;
st.push(make_pair(root,0));
vector<int> vis(n,-1);
vis[root]=1; //This statement is causing segmentation fault
int longest=-1;
while(!st.empty())
{
int top=st.top().first , l=st.top().second;
int x=-1;
for(int i=0;i<adj[top].size();++i)
{
int node = adj[top][i];
if(vis[node] ==-1)
{
x = node;
st.push(make_pair(node,l+1));
vis[node]=1;
break;
}
}
if(x==-1)
{
if(l>l1)
{
l1 = l;
longest = top;
}
st.pop();
}
}
return make_pair(longest,l1);
}
int Solution::solve(vector<int> &A)
{
if(A.size()<3)return (A.size()-1);
vector<vector<int>> adj(A.size());
int root;
for(int i=1;i<A.size();++i)
{
if(A[i]==-1)
{
root = i;
continue;
}
adj[i].push_back(A[i]);
adj[A[i]].push_back(i);
}
//adjacent list for graph complete
pair<int,int> d1=do_dfs(adj,A.size(),root) ;
pair<int,int> d2 = do_dfs(adj, A.size(), d1.first);
int ans = d2.second;
return ans;
}
Tescases :-
A : [ -1, 0, 0, 1, 2, 1, 5 ]
expected output : 5
A : [ -1, 0, 0, 0, 3 ]
expected output : 3
Change the line in Solution::solve(vector<int> &A):
for(int i = 1 ; i < A.size() ; ++i)
To:
for(int i = 0; i < A.size() ; ++i)
And your problem gets solved.
The problem is you're not fully iterating the given A array. You start iterating from the index 1, while the array goes from index 0 to A.size() - 1. So your adjacency list does not get constructed properly, and the root variable remains uninitialized in some cases. So you run into Runtime error.
I'm working on a C++ program where we must traverse a graph of vertices and weighted edges in a way that we start at a user-specified vertex and then end at the same vertex after a certain desired distance has been traveled.
I am not sure how to implement this with code, but I have this so far:
void DijkstrasShortestPath()
{
while (vertices.size() != 0)
{
Vertex* u = extract_min(vertices);
vector<Vertex*>* adjVertex = AdjVertices(u);
const int size = adjVertex->size();
for (int i=0; i<size; ++i)
{
Vertex* v = adjVertex->at(i);
int distance = travel_dist(u, v) +
u->distFromStart;
if (distance < v->distFromStart)
{
v->distFromStart = distance;
v->previous = u;
}
}
delete adjVertex;
}
}
Vertex* extract_min(vector<Vertex*>& vertices)
{
int size = vertices.size();
if (size == 0) {
return NULL;
}
int minimum = 0;
Vertex* min = vertices.at(0);
int i = 0;
for( i=1; i<size; ++i)
{
Vertex* temp = vertices.at(i);
if( temp->distFromStart < min->distFromStart) {
min = temp;
minimum = i;
}
}
vertices.erase(vertices.begin() + minimum);
return min;
}
vector <Vertex*>* AdjVertices(Vertex* vert)
{
vector<Vertex*>* adjVertex = new vector <Vertex*> ();
const int size = edges.size();
for(int i=0; i<size; ++i)
{
Edge* edge = edges.at(i);
Vertex* adjacent = NULL;
if (edge->intersection1 == vert)
{
adjacent = edge->intersection2;
}
else if (edge->intersection2 == vert)
{
adjacent = edge->intersection1;
}
if (adjacent && vertices_check(vertices, adjacent))
{
adjVertex->push_back(adjacent);
}
}
return adjVertex;
}
int travel_dist(Vertex* u, Vertex* v)
{
const int size = edges.size();
for(int i=0; i<size; ++i)
{
Edge* edge = edges.at(i);
if (edge->street_connection(u, v))
{
return edge->distance;
}
}
return -1;
}
bool vertices_check(vector<Vertex*>& vertices, Vertex* vert)
{
const int size = vertices.size();
for(int i=0; i<size; ++i)
{
if (vert == vertices.at(i))
{
return true;
}
}
return false;
}
This is essentially the Dijkstra's Shortest Path algorithm, which is not exactly what I want. What I'm trying to do is get the program to calculate a route thats distance is within 1 unit of a user-specified distance and starts and ends at the same vertex.
Is there any way I can do that by changing what I have?
Does this call for a Breadth-First Search or a Depth-First search instead of Dijkstra's Algorithm?
Dijkstra's algorithm will only store the shortest path from the start node to any other node. What you want instead is to keep track of all paths that lead to a node. If you have those, you can check every time you find a new path to a node if there is a path that has been found before whose length plus the length of the new path is within one unit of the user specified distance. If you then walk one path forward and the other one back you have your loop.
One possible method.
You could use a bounded best-first search.
Create a structure P which stores a list of nodes forming the potential loop, along with the length of the loop created so far.
Seed the search at the specified vertex S by making a separate P-structure for each of the nodes which S links to. Add these P-structures to a priority queue which is sorted by the length of the path described by the P-structure.
Consider each of these nodes in turn removing their P-structures from the priority queue, copying their P-structures, and appending the nodes they link to. If the node to be added is already present in the P-structure and not it is not S, then discard the structure and do not consider that route any longer. Similarly, if any path exceeds the specified cost C, then discard that path and do not consider it any longer. If the path has not been discarded, add its associated P-structure to the priority-queue.
If S does appear in a P-structure twice and the length of the path described by the P-structure is within the permitted range, then exit successfully. If not, continue the search until the priortiy-queue is empty.
You may be able speed up the algorithm by using an admissible heuristic to guesstimate the distance from a given node to S, adding this to the established cost of the path-in-progress, and using the sum as the sorting key for the priority queue. Such heuristics are at the heart of the A* algorithm, which may be of interest to you.
Is this clear? If not, I could writing a short example code.