Problem:
Single Source Shortest Path

For a given weighted graph G(V, E) and a source r, find the source shortest path to each vertex from the source (SSSP: Single Source Shortest Path).

Input

An edge-weighted graph G (V, E) and the source r.

|V| |E| r
s0 t0 d0
s1 t1 d1
:
s|E|-1 t|E|-1 d|E|-1

|V| is the number of vertices and |E| is the number of edges in G. The graph vertices are named with the numbers 0, 1,..., |V|-1 respectively. r is the source of the graph.

si and ti represent source and target vertices of i-th edge (directed) and di represents the cost of the i-th edge.

Output

Print the costs of SSSP in the following format.

c0
c1
:
c|V|-1

The output consists of |V| lines. Print the cost of the shortest path from the source r to each vertex 0, 1, ... |V|-1 in order. If there is no path from the source to a vertex, print INF.

Constraints

1 ≤ |V| ≤ 100000

0 ≤ di ≤ 10000

0 ≤ |E| ≤ 500000

There are no parallel edges

There are no self-loops

Sample Input 1

4 5 0
0 1 1
0 2 4
1 2 2
2 3 1
1 3 5

Sample Output 1

0
1
3
4

Sample Input 2

4 6 1
0 1 1
0 2 4
2 0 1
1 2 2
3 1 1
3 2 5

Sample Output 2

3
0
2
INF

Solution in C (judge verdict: Memory Limit Exceeded)

#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void *xmalloc(size_t size) {
  void *ptr = malloc(size);
  if (ptr == NULL) {
    fprintf(stderr, "Failed to allocate memory\n");
    exit(EXIT_FAILURE);
  }
  return ptr;
}

typedef struct {
  void **data;
  size_t capacity;
  size_t len;
} Vector;

#define VECTOR_DEFAULT_CAPACITY 16

Vector *new_vec_with(size_t capacity) {
  Vector *v = xmalloc(sizeof(Vector));
  v->data = xmalloc(sizeof(void *) * capacity);
  memset(v->data, 0, sizeof(void *) * capacity);
  v->capacity = capacity;
  v->len = 0;
  return v;
}

Vector *new_vec() { return new_vec_with(VECTOR_DEFAULT_CAPACITY); }

void vec_expand(Vector *v, size_t size) {
  if (v->len < size) {
    v->capacity = size;
    v->len = size;
    v->data = realloc(v->data, sizeof(void *) * v->capacity);
  }
}

void vec_push(Vector *v, void *elem) {
  if (v->len == v->capacity) {
    v->capacity *= 2;
    v->data = realloc(v->data, sizeof(void *) * v->capacity);
  }
  v->data[v->len++] = elem;
}

void *vec_pop(Vector *v) {
  assert(v->len);
  return v->data[--v->len];
}

#define VecForeachWithType(vec, T, loop_val, loop_body)                        \
  for (size_t fe_loop_counter_##vec = 0; fe_loop_counter_##vec < vec->len;     \
       fe_loop_counter_##vec++) {                                              \
    T loop_val = vec->data[fe_loop_counter_##vec];                             \
    loop_body;                                                                 \
  }

#define VecForeach(vec, loop_val, loop_body)                                   \
  VecForeachWithType(vec, void *, loop_val, loop_body)

typedef int (*ELEM_COMPARE)(void *, void *);

typedef struct {
  Vector *vec;
  ELEM_COMPARE compare;
} BinaryHeap;

#define GetHeapVec(heap) (heap->vec)
#define GetHeapData(heap, i) (heap->vec->data[i])

BinaryHeap *new_BinaryHeap(ELEM_COMPARE compare) {
  BinaryHeap *heap = xmalloc(sizeof(BinaryHeap));
  heap->vec = new_vec();
  heap->compare = compare;
  return heap;
}

void heap_insert(BinaryHeap *heap, void *val) {
  size_t n = GetHeapVec(heap)->len;
  vec_push(GetHeapVec(heap), val);

  while (n != 0) {
    size_t i = (n - 1) / 2;

    // heap->vec->data[n] > heap->vec->data[i]
    if (heap->compare(GetHeapData(heap, n), GetHeapData(heap, i)) == 1) {
      void *tmp = GetHeapData(heap, n);
      GetHeapData(heap, n) = GetHeapData(heap, i);
      GetHeapData(heap, i) = tmp;
    }

    n = i;
  }
}

void *heap_pop(BinaryHeap *heap) {
  assert(GetHeapVec(heap)->len > 0);

  size_t n = GetHeapVec(heap)->len - 1;
  void *ret = GetHeapData(heap, 0);
  GetHeapData(heap, 0) = GetHeapData(heap, n);
  vec_pop(GetHeapVec(heap));

  for (size_t i = 0, j; (j = 2 * i + 1) < n;) {
    if ((j != n - 1) &&
        heap->compare(GetHeapData(heap, j), GetHeapData(heap, j + 1)) == -1) {
      j++;
    }

    if (heap->compare(GetHeapData(heap, i), GetHeapData(heap, j)) == -1) {
      void *tmp = GetHeapData(heap, j);
      GetHeapData(heap, j) = GetHeapData(heap, i);
      GetHeapData(heap, i) = tmp;
    }

    i = j;
  }

  return ret;
}

bool heap_empty(BinaryHeap *heap) { return GetHeapVec(heap)->len == 0; }

typedef struct {
  BinaryHeap *heap;
} PriorityQueue;

PriorityQueue *new_PriorityQueue(ELEM_COMPARE compare) {
  PriorityQueue *pqueue = xmalloc(sizeof(PriorityQueue));
  pqueue->heap = new_BinaryHeap(compare);
  return pqueue;
}

void pqueue_push(PriorityQueue *pqueue, void *elem) {
  heap_insert(pqueue->heap, elem);
}

void *pqueue_pop(PriorityQueue *pqueue) { return heap_pop(pqueue->heap); }

bool pqueue_empty(PriorityQueue *pqueue) { return heap_empty(pqueue->heap); }

const int INF = 1 << 30;

typedef struct {
  int dst;
  int cost;
} Edge;

Edge *new_Edge(int dst, int cost) {
  Edge *edge = xmalloc(sizeof(Edge));
  edge->dst = dst;
  edge->cost = cost;
  return edge;
}

static int cmp_Edge(void *lhs, void *rhs) {
  Edge *le = (Edge *)lhs;
  Edge *re = (Edge *)rhs;

  if (le->cost >= re->cost) {
    return 1;
  } else {
    return -1;
  }
}

#define INT_TO_VoPTR(i) ((void *)(intptr_t)i)
#define VoPTR_TO_INT(ptr) ((int)(intptr_t)ptr)

Vector *dijkstra(Vector *tree, int src) {
  int V = tree->len;
  Vector *dist = new_vec_with(V);
  for (size_t i = 0; i < V; i++) {
    dist->data[i] = INT_TO_VoPTR(INF);
  }

  PriorityQueue *pqueue = new_PriorityQueue(cmp_Edge);

  dist->data[src] = 0;
  pqueue_push(pqueue, new_Edge(src, 0));

  while (!pqueue_empty(pqueue)) {
    Edge *e = pqueue_pop(pqueue);
    int v = e->dst, cost = e->cost;

    if (VoPTR_TO_INT(dist->data[v]) < cost) {
      continue;
    }

    Vector *vec = tree->data[v];
    VecForeachWithType(vec, Edge *, e, {
      if (VoPTR_TO_INT(dist->data[v]) + e->cost <
          VoPTR_TO_INT(dist->data[e->dst])) {
        dist->data[e->dst] =
            INT_TO_VoPTR(VoPTR_TO_INT(dist->data[v]) + e->cost);
        pqueue_push(pqueue, new_Edge(e->dst, VoPTR_TO_INT(dist->data[e->dst])));
      }
    });
  }

  return dist;
}

int main(void) {
  int V, E, r;
  scanf("%d%d%d", &V, &E, &r);

  Vector *tree = new_vec();
  for (size_t i = 0; i < V; i++) {
    vec_push(tree, new_vec());
  }

  for (int i = 0; i < E; i++) {
    int s, t, d;
    scanf("%d%d%d", &s, &t, &d);
    vec_push(tree->data[s], new_Edge(t, d));
  }

  Vector *ret = dijkstra(tree, r);

  for (size_t i = 0; i < V; i++) {
    Vector *v = tree->data[i];
    for (size_t j = 0; j < v->len; j++) {
      free(v->data[j]);
    }
    free(v);
  }

  for (int i = 0; i < V; i++) {
    int result = VoPTR_TO_INT(ret->data[i]);
    if (result >= INF) {
      printf("INF\n");
    } else {
      printf("%ld\n", result);
    }
  }

  return 0;
}