Cod sursa(job #2774793)

Utilizator mircea_007Mircea Rebengiuc mircea_007 Data 12 septembrie 2021 19:52:01
Problema Algoritmul lui Dijkstra Scor 20
Compilator c-64 Status done
Runda Arhiva educationala Marime 2.9 kb
#include <stdio.h>
#include <ctype.h>

// Program de Mircea Rebengiuc
// inceput pe 2021.09.12

#define MAXN 50000
#define MAXM 250000
#define NIL  -1
#define START 0
#define INF 2000000000

int list[MAXN];
int next[MAXM];
int adj[MAXM];
int cost[MAXM];

int visited[MAXN];
int dist[MAXN];

int heap[MAXN];
int node2h[MAXN];
int hn;

static inline int minLRP( int node ){
  int c = node * 2 + 1, min = node;

  if( c < hn && dist[heap[c]] < dist[heap[min]] )
    min = c;

  c++;

  if( c < hn && dist[heap[c]] < dist[heap[min]] )
    min = c;

  return min;
}

static inline void heapSwap( int a, int b ){
  int aux;

  aux = heap[a];
  heap[a] = heap[b];
  heap[b] = aux;

  a = heap[a];
  b = heap[b];
  
  aux = node2h[a];
  node2h[a] = node2h[b];
  node2h[b] = aux;
}

static inline void fall( int node ){
  int aux;
  
  while( (aux = minLRP(node)) != node ){
    heapSwap(aux, node);
    node = aux;
  }
}

static inline void rise( int node ){
  int p;
  
  while( dist[heap[p = ((node - 1) / 2)]] > dist[heap[node]] ){
    heapSwap(p, node);
    node = p;
  }
}

static inline int pop(){
  int retval = heap[0];

  heapSwap(0, hn - 1);
  hn--;

  fall(0);

  return retval;
}

static inline void update( int node, int val ){
  if( node2h[node] == NIL ){// do we have to insert?
    node2h[node] = hn;
    heap[hn] = node;
    dist[node] = val;
    hn++;
    rise(hn - 1);
  }else{
    dist[node] = val;
    rise(node2h[node]);
  }
}


void printHeap( int node, int indent ){
  int i;
  
  if( node >= hn )
    return;

  printHeap(node * 2 + 1, indent + 2);
  for( i = 0 ; i < indent ; i++ )
    fputc(' ', stdout);
  printf("(%d, %d)\n", heap[node], dist[heap[node]]);
  printHeap(node * 2 + 2, indent + 2);
}


FILE *fin, *fout;

static inline int fgetint(){
  int n = 0, ch;

  while( !isdigit(ch = fgetc(fin)) );
  do
    n = n * 10 + ch - '0';
  while( isdigit(ch = fgetc(fin)) );

  return n;
}

int main(){
  fin  = fopen("dijkstra.in",  "r");
  fout = fopen("dijkstra.out", "w");

  int n, m, i, a, b, c;

  n = fgetint();
  m = fgetint();
  for( i = 0 ; i < n ; i++ ){
    list[i] = NIL;
    node2h[i] = NIL;
    dist[i] = INF;
    visited[i] = 0;
  }

  for( i = 0 ; i < 2 * m ; i += 2 ){
    a = fgetint() - 1;
    b = fgetint() - 1;
    c = fgetint();

    next[i] = list[a];
    list[a] = i;
    adj[i] = b;
    cost[i] = c;

    next[i + 1] = list[b];
    list[b] = i + 1;
    adj[i + 1] = a;
    cost[i + 1] = c;
  }

  hn = 0;
  update(START, 0);
  while( hn > 0 ){
    //printHeap(0, 1);
    visited[a = pop()] = 1;
    //printf("a = %d -> dist = %d\n", a, dist[a]);

    i = list[a];
    while( i != NIL ){
      if( !visited[adj[i]] )
        if( dist[adj[i]] > dist[a] + cost[i] )
          update(adj[i], dist[a] + cost[i]);
      
      i = next[i];
    }
  }

  for( i = 0 ; i < n ; i++ )
    if( i != START )
      fprintf(fout, "%d ", dist[i] == INF ? 0 : dist[i]);
  fputc('\n', fout);

  fclose(fin);
  fclose(fout);
  return 0;
}