Thursday, December 31, 2009

Dijkstra's Algorithm in C++


Dijkstra's Algorithm


Dijkstra's algorithm is a single source shortest path (sssp) algorithm. Like BFS, this famous graph searching algorithm is widely used in programming and problem solving, generally used to determine shortest tour in a weighted graph.


This algorithm is almost similar to standard BFS, but instead of using a Queue data structure, it uses a heap like data structure or a priority queue to maintain the weight order of nodes. Here is the algorithm and pseudo-code. You can also look into Introduction to Algorithms (by C.L.R.S).


Here is a short implementation of this algorithm in C++, I assumed that, all the edge-weights are positive, and the max possible distance is less than 220 which is set as INF macro and the graph supports MAX nodes starting from 1 to MAX-1, these macros needs to be set properly.


Input format:



N E // number of nodes and edges
E lines containing an edge (u, v, w) on each line
// edge(u, v, w) means weight of edge u-v is w
// u, v in range 1 to N
S // starting node

C++ code:



#include <cstdio>
#include <queue>
#include <vector>
using namespace std;

#define MAX 100001
#define INF (1<<20)
#define DEBUG if(0)
#define pii pair< int, int >
#define pb(x) push_back(x)

struct comp {
bool operator() (const pii &a, const pii &b) {
return a.second > b.second;
}
};

priority_queue< pii, vector< pii >, comp > Q;
vector< pii > G[MAX];
int D[MAX];
bool F[MAX];

int main() {
int i, u, v, w, sz, nodes, edges, starting;
DEBUG freopen("in.txt","r", stdin);

// create graph
scanf("%d %d", &nodes, &edges);
for(i=0; i<edges; i++) {
scanf("%d %d %d", &u, &v, &w);
G[u].pb(pii(v, w));
G[v].pb(pii(u, w)); // for undirected
}
scanf("%d", &starting);

// initialize graph
for(i=1; i<=nodes; i++) D[i] = INF;
D[starting] = 0;
Q.push(pii(starting, 0));

// dijkstra
while(!Q.empty()) {
u = Q.top().first;
Q.pop();
if(F[u]) continue;
sz = G[u].size();
DEBUG printf("visiting from %d:", u);
for(i=0; i<sz; i++) {
v = G[u][i].first;
w = G[u][i].second;
if(!F[v] && D[u]+w < D[v]) {
DEBUG printf(" %d,", v);
D[v] = D[u] + w;
Q.push(pii(v, D[v]));
}
}
DEBUG printf("\n");
F[u] = 1; // done with u
}

// result
for(i=1; i<=nodes; i++) printf("Node %d, min weight = %d\n", i, D[i]);
return 0;
}

This is a straight forward implementation, according to the problem solving purpose, changes are to be made here and there.



8 comments:

  1. One thing. If a node has been push more then one time it will also pop more then one times. Consider the graph;
    6 6
    1 2 3
    1 4 7
    2 3 10
    2 4 3
    4 5 1
    4 6 2
    1
    Here 4 is pop'ed 2 times. I know its should not cause any problem but is not it unnecessary? If we do like below is there could be any problem?

    // dijkstra
    while(!Q.empty()) {
    u = Q.top().first;
    Q.pop();
    if(F[u]) continue; //If already done forget it
    sz = G[u].size();

    ReplyDelete
  2. No, It will not cause any trouble. You can do that :)

    ReplyDelete
  3. Can you please suggest how to modify the code if I want to find the shortest path for any 2 nodes?

    Thx so much

    ReplyDelete
  4. @Jo, I guess you were talking about all-pair shortest paths (so that you might get shortest path between any two nodes).
    Well, dijkstra won't be able to solve that easily, you could have run dijkstra once for each query.
    But there are more straight forward ways to get that. Use floyed warshall or johnson's algorithms.
    Floyed Warshall is very easy.

    ReplyDelete
  5. I keeping just for Dijkstra's Algorithm c++ codes and accidentally came here. I coded my assignment of Dijkstra's Algorithm in 2D array and i have problems implement it. Any idea or what good website gives sample codes of Dijkstra's Algorithm. The Dijkstra's i know how it works in paper, however when comes to coding, i'm not really good at it.
    I have try to compile your code successfully, but i dont have the text file of in.txt. Please you show the file to run ur code.

    ReplyDelete
  6. Hi, forget the in.txt thing, if you look carefully, that line is disabled. All you need to do is just enter the input graph, follow this format:
    First give two integers:
    # of nodes: n and # of edges: e
    Then e lines each containing and edge:
    u v w where the edge is u<--->v having weight w
    done!

    If you want to use a directed graph, then look, in the input area, remove this line:
    G[v].pb(pii(u, w));

    Hope you can do it now, but actually I didn't believe what you have written, I mean, if you know C++ then this code is very easy to understand, at least anyone can determine the input format from it! and if you don't know the language or don't know how to implement dijkstra, that will be a clear cheating, don't do that, learn the hard way :)

    ReplyDelete
  7. Obfuscated code.... If this were an application that required collaboration you would be scolded.

    Seriously the choice of variable names makes me want to strangle you.

    ReplyDelete
    Replies
    1. I am afraid you are in a wrong place, this is no place for software developers and this NEVER will require collaboration. This program is PERFECTLY OK for contest programming. Anyways, thanks for visiting my blog :)

      Delete

Catagories

academic study (17) access modifiers (1) algorithm (28) bash (1) beginner (17) bfs (1) bigint (1) binary tree (1) bitwise (4) blogger (5) bpm (2) brainfuck (1) bst (1) c (1) c++ (36) changes (1) character device driver (1) combinatorics (2) command prompt (1) comparator (1) compression (1) computational geometry (2) confusion (1) contest (7) crc (1) cse (3) css (1) customize (1) data structure (10) database (1) decoding (1) design (1) device driver (1) divide and conquer (2) dp (3) driver (1) dynamic programming (9) encoding (1) encryption (1) error (2) esoteric language (2) euler circuit (1) euler path (1) executable (1) expression evaluation (1) extended euclid (1) facebook (1) factorization (1) funny (14) gcd (2) geometry (4) git (1) github (1) graph (7) hashing (1) hiding window (1) hints (5) hopcroft karp (1) huffman (1) jar (1) java (5) javascript (1) jdbc (1) kernel programming (2) lab (1) like (1) linear algebra (3) linux (5) ls (1) makefile (1) math (16) matrix (2) matrix algebra (1) matrix exponentiation (1) matrix multiplication (1) maxflow (1) maximum bipartite matching (2) maximum flow (1) merge sort (3) mistake (1) modular arithmatic (1) module compiling (2) mysql (1) number system (1) number theory (8) online judge (3) operating system (1) os (1) other (8) parallel programming (1) pollard rho (1) primes (3) problem (3) problem classifier (2) problem solving (34) programming (51) pthreaded (1) puzzle (1) python (3) recursion (5) repository (1) shell (1) shell script (1) sieve (1) simulation (1) sort (3) spacing (1) sphere online judge (12) spoj (12) syntax highlighting (1) system programming (4) table tag (1) tc (1) template (4) thread (1) topcoder (1) training (3) tree (1) tutorial (2) ubuntu (1) usaco (1) uva (5) uva online judge (5) vector (1) windows (1)