diff --git a/dijkstra.c b/dijkstra.c
index c65c037c852a054e4a76c1043061c6633d898139..d3e99073183fef95157be767c0722a47d51053e2 100644
--- a/dijkstra.c
+++ b/dijkstra.c
@@ -4,113 +4,151 @@
 #include <stdlib.h>
 #include <limits.h>
 
-int NUMBER_OF_VERTICES = 0;
+int N = 0;
 
 long getVertexWithMinDistance(long dist[], bool pickedVertices[]) {
-  long minDistance = LONG_MAX;
-  int vertexWithMinDistance = -1;
-
-  for (int vertex = 0; vertex < NUMBER_OF_VERTICES; vertex++) {
-    if (!pickedVertices[vertex] && dist[vertex] <= minDistance) {
-      minDistance = dist[vertex];
-      vertexWithMinDistance = vertex;
+    long minDistance = LONG_MAX;
+    int vertexWithMinDistance = -1;
+
+    for (int vertex = 0; vertex < N; vertex++) {
+        if (!pickedVertices[vertex] && dist[vertex] <= minDistance) {
+            minDistance = dist[vertex];
+            vertexWithMinDistance = vertex;
+        }
     }
-  }
-  return vertexWithMinDistance;
+    return vertexWithMinDistance;
 }
 
-void dijkstra(int graph[NUMBER_OF_VERTICES][NUMBER_OF_VERTICES], int sourceVertex) {
+long* dijkstra(int graph[N][N], int sourceVertex) {
 
-  // Distance from single source to all of the nodes
-  long dist[NUMBER_OF_VERTICES];
-  bool pickedVertices[NUMBER_OF_VERTICES];
+    // Distance from single source to all of the nodes
+    long *dist = (long*) malloc(sizeof(long) * N);
+    bool pickedVertices[N];
 
-  for (int vertex = 0; vertex < NUMBER_OF_VERTICES; vertex++) {
-    if (vertex == sourceVertex) {
-      dist[vertex] = 0; 
-    } else {
-      // Initialize all distance to be infinity.
-      dist[vertex] = LONG_MAX;
+    for (int vertex = 0; vertex < N; vertex++) {
+        if (vertex == sourceVertex) {
+            dist[vertex] = 0; 
+        } else {
+            // Initialize all distance to be infinity.
+            dist[vertex] = LONG_MAX;
+        }
+        pickedVertices[vertex] = false;
     }
-    pickedVertices[vertex] = false;
-  }
 
-  for (int iteration = 0; iteration < NUMBER_OF_VERTICES - 1; iteration++) {
-    // Get minimum distance
-    int vertexWithMinDistance = getVertexWithMinDistance(dist, pickedVertices);
+    for (int iteration = 0; iteration < N - 1; iteration++) {
+        // Get minimum distance
+        int vertexWithMinDistance = getVertexWithMinDistance(dist, pickedVertices);
+
+        // Mark the vertice as picked
+        pickedVertices[vertexWithMinDistance] = true;
+
+        // Update distance value
+        for (int vertex = 0; vertex < N; vertex++) {
+            if ((!pickedVertices[vertex]) && 
+                (graph[vertexWithMinDistance][vertex]) && 
+                (dist[vertexWithMinDistance] != LONG_MAX) && 
+                (dist[vertexWithMinDistance] + graph[vertexWithMinDistance][vertex] < dist[vertex])) {
+                // Change dist[]
+                dist[vertex] = dist[vertexWithMinDistance] + graph[vertexWithMinDistance][vertex];
+            }
+        }
+    }
 
-    // Mark the vertice as picked
-    pickedVertices[vertexWithMinDistance] = true;
+    return dist;
 
-    // Update distance value
-    for (int vertex = 0; vertex < NUMBER_OF_VERTICES; vertex++) {
-      if (!pickedVertices[vertex] && graph[vertexWithMinDistance][vertex] && dist[vertexWithMinDistance] != LONG_MAX && dist[vertexWithMinDistance] + graph[vertexWithMinDistance][vertex] < dist[vertex]) {
-        dist[vertex] = dist[vertexWithMinDistance] + graph[vertexWithMinDistance][vertex];
-      }
-    }
-  }
-
-  // Edit the real graph
-  for (int vertex = 0; vertex < NUMBER_OF_VERTICES; vertex++) {
-    graph[sourceVertex][vertex] = dist[vertex];
-  }
-
-  // Print solution
-  for (int vertex = 0; vertex < NUMBER_OF_VERTICES; vertex++) {
-    // printf("%d to %ld\n", vertex, dist[vertex]);
-    printf("%d to %d\n", vertex, graph[sourceVertex][vertex]);
-  }
+    // // Print solution
+    // for (int vertex = 0; vertex < N; vertex++) {
+    //     // printf("%d to %ld\n", vertex, dist[vertex]);
+    //     printf("%d to %d\n", vertex, graph[sourceVertex][vertex]);
+    // }
 }
 
 int main(int argc, char *argv[]) {
 
-  // Get matrix size from argument vector in , convert to int
-  NUMBER_OF_VERTICES = strtol(argv[1], NULL, 10);
-
-  // Initialize matrix
-  int graph[NUMBER_OF_VERTICES][NUMBER_OF_VERTICES];
-
-  // Seed with NIM: Edward Alexander Jaya
-  srand(13517115);
-  // Fill the matrix with rand() function
-  for (int i = 0; i < NUMBER_OF_VERTICES; i++) {
-    for (int j = 0; j < NUMBER_OF_VERTICES; j++) {
-      // Mod by 100 so the result won't be too big.
-      graph[i][j] = rand() % 100;
+    // Test function
+    
+    // for (int i = 0; i < N; i++) {
+    //     for (int j = 0; j < N; j++) {
+    //         scanf("%d", &graph[i][j]);
+    //     }
+    // }
+
+    // graph = { 0, 4, 0, 0, 0, 0, 0, 8, 0,
+    //                     4, 0, 8, 0, 0, 0, 0, 11, 0, 
+    //                     0, 8, 0, 7, 0, 4, 0, 0, 2, 
+    //                     0, 0, 7, 0, 9, 14, 0, 0, 0, 
+    //                     0, 0, 0, 9, 0, 10, 0, 0, 0, 
+    //                     0, 0, 4, 14, 10, 0, 2, 0, 0, 
+    //                     0, 0, 0, 0, 0, 2, 0, 1, 6, 
+    //                     8, 11, 0, 0, 0, 0, 1, 0, 7, 
+    //                     0, 0, 2, 0, 0, 0, 6, 7, 0 };
+
+    // dijkstra(graph, 1); 
+
+    // // Print function
+    // printf("Matrix: \n");
+    // for (int i = 0; i < N; i++) {
+    //     for (int j = 0; j < N; j++) {
+    //         printf("%d ", graph[i][j]);
+    //     }
+    //     printf("\n");
+    // }
+
+    // Get matrix size from argument vector in , convert to int
+    N = strtol(argv[1], NULL, 10);
+    
+    // Initialize matrix
+    int graph[N][N];
+
+    // Seed with NIM: Edward Alexander Jaya
+    srand(13517115);
+    // Fill the matrix with rand() function
+    for (int i = 0; i < N; i++) {
+        for (int j = 0; j < N; j++) {
+            // Mod by 100 so the result won't be too big.
+            graph[i][j] = rand() % 100;
+        }
     }
-  }
-
-  // Test function
-  
-  // for (int i = 0; i < NUMBER_OF_VERTICES; i++) {
-  //   for (int j = 0; j < NUMBER_OF_VERTICES; j++) {
-  //     scanf("%d", &graph[i][j]);
-  //   }
-  // }
-
-  // graph = { 0, 4, 0, 0, 0, 0, 0, 8, 0,
-  //           4, 0, 8, 0, 0, 0, 0, 11, 0, 
-  //           0, 8, 0, 7, 0, 4, 0, 0, 2, 
-  //           0, 0, 7, 0, 9, 14, 0, 0, 0, 
-  //           0, 0, 0, 9, 0, 10, 0, 0, 0, 
-  //           0, 0, 4, 14, 10, 0, 2, 0, 0, 
-  //           0, 0, 0, 0, 0, 2, 0, 1, 6, 
-  //           8, 11, 0, 0, 0, 0, 1, 0, 7, 
-  //           0, 0, 2, 0, 0, 0, 6, 7, 0 };
-
-  dijkstra(graph, 1); 
-
-  // Print function
-  printf("Matrix: \n");
-  for (int i = 0; i < NUMBER_OF_VERTICES; i++) {
-    for (int j = 0; j < NUMBER_OF_VERTICES; j++) {
-      printf("%d ", graph[i][j]);
+
+    MPI_Status Stat;
+    MPI_Init(&argc, &argv);
+    // rank is the id of processes,  numtasks is the number of processes
+    int rank, numtasks;
+    MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+    double start_time, end_time, total_time = 0.0;
+
+    int numOfTaskPerProcess = N / (numtasks - 1);
+    int destinationRank = 0;
+    int tag = 1;
+    int vertex = 0;
+
+    // for each thread, synchronize before start
+    MPI_Barrier(MPI_COMM_WORLD);
+        
+    // Do not count the initial synchronization time
+    start_time = MPI_Wtime();
+
+    if (rank == 0) {
+        long* dataRecv;
+        // Receive
+        MPI_Recv(&dataRecv, N, MPI_LONG, MPI_ANY_SOURCE, tag, MPI_COMM_WORLD, &Stat);
+        printf("Received from process %d ", MPI_ANY_SOURCE);
+        // To do: store in the array
+        free(dataRecv);
+    } else {
+        for (int vertex = (rank - 1) * numOfTaskPerProcess; vertex < (rank - 1) * numOfTaskPerProcess + numOfTaskPerProcess; vertex++) {
+            long* dataSend = dijkstra(graph, vertex);
+            MPI_Send(dataSend, N, MPI_LONG, destinationRank, tag, MPI_COMM_WORLD);
+            // Possible bug
+            free(dataSend);
+        }
     }
-    printf("\n");
-  }
 
-  // Send argument vector
-  MPI_Init(&argc, &argv);
-  // dijkstra(graph, 0); 
-  MPI_Finalize();
+    // Synchronize again and count the time
+    MPI_Barrier(MPI_COMM_WORLD);
+    end_time = MPI_Wtime();
+    total_time = end_time - start_time;
+    MPI_Finalize();
 } 
diff --git a/prog b/prog
index 36dc0edffef02f645890ce0603622a4818a177b6..bc7444f0404da1a31988e24d3001a7225c403486 100755
Binary files a/prog and b/prog differ