Advertisement
Guest User

Footing (2)

a guest
Feb 18th, 2016
169
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.98 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <limits.h>
  4. #include <assert.h>
  5. #include "minqueue.h"
  6.  
  7. #define new_node() malloc(sizeof(listnode))
  8. #define node type
  9. #define min(a,b) ((a) < (b)) ? (a) : (b)
  10.  
  11. typedef int vertice;
  12.  
  13. typedef struct _arco {
  14.     vertice from;
  15.     vertice to;
  16.     int peso;
  17. } arco;
  18.  
  19. /* Elemento della lista di adiacenza */
  20. typedef struct _elem {
  21.     vertice from;
  22.     vertice to;
  23.     int peso;
  24.     struct _elem *next;
  25. } listnode;
  26.  
  27. const int INF = INT_MAX; // L'infinito di Dijkstra
  28.  
  29. // Inserisce nella lista di adiacenza del primo vertice, il secondo col peso indicato come quarto parametro
  30. void insert(listnode**, vertice, vertice, int);
  31.  
  32. int best_cycle(int start, int n, listnode** adj);
  33.  
  34. int main(void) {
  35.     int n, m; // n = #nodi, m = #archi
  36.     listnode** vertici; // Liste di adiacenza
  37.     arco* archi;
  38.     int from, to, weight;
  39.    
  40.     FILE *fin, *fout;
  41.     int i, j;
  42.    
  43.     fin = fopen("input.txt","r");
  44.     fout = fopen("output.txt","w");
  45.     assert(fin != NULL && fout != NULL);
  46.    
  47.     assert(2 == fscanf(fin, "%i %i", &n, &m)); // Leggo n & m
  48.    
  49.     vertici = calloc(n, sizeof *vertici);
  50.     archi = malloc(2 * m * sizeof *archi);
  51.     assert(vertici != NULL && archi != NULL);
  52.    
  53.     for(i=0;i<m;i++) {
  54.         assert(3 == fscanf(fin, "%i %i %i", &from, &to, &weight));
  55.         /* Zero Based */
  56.         from--;
  57.         to--;
  58.        
  59.         // Inserisco l'arco (inutile)
  60.         archi[i].from = from;
  61.         archi[i].to = to;
  62.         archi[i].peso = weight;
  63.         // E l'arco contrario
  64.         archi[2*m-i-1].from = to;
  65.         archi[2*m-i-1].to = from;
  66.         archi[2*m-i-1].peso = weight;
  67.        
  68.         // Popolo la lista di adiacenza
  69.         insert(vertici, from, to, weight);
  70.         insert(vertici, to, from, weight);
  71.     }
  72.    
  73.     int ciclo_minimo = best_cycle(0, n, vertici); // Cerco un ciclo a partire dal primo nodo
  74.     for(i=1;i<n;i++) {
  75.  
  76.         int ciclo = best_cycle(i, n, vertici); // Cerco un ciclo per ogni altro nodo
  77.         ciclo_minimo = (ciclo < ciclo_minimo) ? ciclo : ciclo_minimo; // Guardo se è migliore di quello che avevo prima
  78.     }
  79.     fprintf(fout, "%i", ciclo_minimo);
  80.    
  81.     /* CLEAN UP */
  82.     for(i=0;i<n;i++) {
  83.         listnode *v = vertici[i];
  84.         while(v != NULL) {
  85.             listnode *tmp = v;
  86.             v = v->next;
  87.             free(tmp);
  88.         }
  89.     }
  90.     free(vertici);
  91.     free(archi);
  92.     fclose(fin);
  93.     fclose(fout);
  94. }
  95.  
  96. // Popola la lista di adiacenza di u, inserendo l'arco (u,v) di peso w
  97. void insert(listnode** list, int u, int v, int w) {
  98.     listnode *new = new_node();
  99.     new->from = u;
  100.     new->to = v;
  101.     new->peso = w;
  102.     new->next = NULL;
  103.    
  104.     if(list[u] == NULL) {
  105.         list[u] = new;
  106.     }
  107.     else {
  108.         listnode *curr = list[u];
  109.         listnode *prec = NULL;
  110.         while(curr != NULL) {
  111.             prec = curr;
  112.             curr = curr->next;
  113.         }
  114.         prec->next = new;
  115.     }
  116. }
  117.  
  118.  
  119. int best_cycle(int start, int n, listnode** adj) {
  120.     /* La struttura memorizzata nella coda è così formata:
  121.      * { weight, parent, endpoint }
  122.      * (qui chiamati rispettivamente: key, parent, nodo)
  123.     **/
  124.     int ciclo_minimo = INF; // L'equivalente di int best = std::numeric_limits<int>::max();
  125.     int *distanze = malloc(n*sizeof(int)); // Equivale a  std::vector<int> dist(N, std::numeric_limits<int>::max());
  126.     int i;
  127.    
  128.     assert(distanze != NULL);
  129.     // Inizializzo tutto dist[] a infinito
  130.     for(i=0;i<n;i++) {
  131.         distanze[i] = INF;
  132.     }
  133.    
  134.     heap_init(); // Creo la coda
  135.    
  136.     enqueue((node){0, -1, start}); // Inserisco il primo nodo (q.push({start, 0, -1}))
  137.     while(!empty_queue()) {
  138.         node current = extract_min(); // ( auto t = q.top(); q.pop(); )
  139.        
  140.         int u = current.nodo; // t.endpoint
  141.         int w = current.key; // t.weight
  142.         int p = current.parent; // t.parent
  143.        
  144.         if(distanze[u] == INF) { // Non ho mai visto il nodo
  145.             distanze[u] = w;
  146.         }
  147.         else {
  148.             // Ho già visto il nodo e quindi formo un ciclo
  149.             ciclo_minimo = min(ciclo_minimo, distanze[u] + w);
  150.             continue;
  151.         }
  152.        
  153.         listnode *FS = adj[u];
  154.         // Scorro la lista di adiacenza di u
  155.         while(FS != NULL) {
  156.             if(FS->to != p) { // Non torno sul padre
  157.                 enqueue((node){w + FS->peso, u, FS->to});
  158.             }
  159.             FS = FS->next;
  160.         }
  161.     }
  162.    
  163.     free(distanze);
  164.    
  165.     heap_destroy();
  166.    
  167.     return ciclo_minimo;
  168. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement