/*--------------------------------------------------- / Author: Ana Paula Tomas / Date: November 2016 / Solves "white rabbit" /---------------------------------------------------*/ #include #include //#define DEBUG #define NMAX 201 #define CMAX 200 #define INFTY CMAX*13+1 static int INV13[13] = {0,1,7,9,10,8,11,2,5,3,4,6,12}; // not defined for 0 #define NORM13(V) ((V)%13 >= 0? (V)%13: 13+(V)%13) int Mat[CMAX+1][CMAX+1], D[CMAX]; typedef struct edge { int vertex, weight; struct edge *nxt; } EDGE; #define DEST(edge) ((edge) -> vertex) #define WEIGHT(edge) ((edge) -> weight) #define NXTADJ(edge) ((edge) -> nxt) typedef struct { EDGE *adjs; } NODE; #define DIST(no) ((no).dist) #define ADJS(no) ((no).adjs) NODE Graph[NMAX+1]; void elementary_transf(int pivot,int r,int lines,int cols){ int j; for (j=1;j<=cols;j++) { Mat[lines][j] -= Mat[r][j]*pivot; Mat[lines][j] = NORM13(Mat[lines][j]); } D[lines] -= D[r]*pivot; D[lines] = NORM13(D[lines]); } EDGE *new_edge(int v,int weight,EDGE* nxt) { EDGE *e = (EDGE *) malloc(sizeof(EDGE)); DEST(e) = v; WEIGHT(e) = weight; NXTADJ(e) = nxt; return e; } void find_graph(int n, int ntrips) { int lines=0, columns=0, oldcolumns, ne; int vbas[CMAX+1], Column[CMAX+1][2], i, j, t, x, y, aux; int Index[NMAX+1][NMAX+1] = {0}; for(t=0;t=0;i--) { for(j=i+1;j a[i].vertkey < q -> a[j].vertkey) return -1; if (q -> a[i].vertkey == q -> a[j].vertkey) return 0; return 1; } static int pos_valida(int i, HEAPMIN *q) { return (i >= 1 && i <= q -> size); } int extractMin(HEAPMIN *q) { int vertv = q -> a[1].vert; swap(1,q->size,q); q -> pos_a[vertv] = POSINVALIDA; // vertv was removed q -> size--; heapify(1,q); return vertv; } void decreaseKey(int vertv, int newkey, HEAPMIN *q){ int i = q -> pos_a[vertv]; q -> a[i].vertkey = newkey; while(i > 1 && compare(i,PARENT(i),q) < 0){ swap(i,PARENT(i),q); i = PARENT(i); } } static void heapify(int i,HEAPMIN *q) { // min-heap int l, r, smallest; l = LEFT(i); if (l > q -> size) l = i; r = RIGHT(i); if (r > q -> size) r = i; smallest = i; if (compare(l,smallest,q) < 0) smallest = l; if (compare(r,smallest,q) < 0) smallest = r; if (i != smallest) { swap(i,smallest,q); heapify(smallest,q); } } static void swap(int i,int j,HEAPMIN *q){ QNODE aux; q -> pos_a[q -> a[i].vert] = j; q -> pos_a[q -> a[j].vert] = i; aux = q -> a[i]; q -> a[i] = q -> a[j]; q -> a[j] = aux; } HEAPMIN *build_heap_min(int vec[], int n){ // the elements are in vec[1] .. vec[n] // builds the corresponding heapMin in time O(n) HEAPMIN *q = (HEAPMIN *)malloc(sizeof(HEAPMIN)); int i; q -> a = (QNODE *) malloc(sizeof(QNODE)*(n+1)); q -> pos_a = (int *) malloc(sizeof(int)*(n+1)); q -> sizeMax = n; // position 0 is kept free q -> size = n; for (i=1; i<= n; i++) { q -> a[i].vert = i; q -> a[i].vertkey = vec[i]; q -> pos_a[i] = i; // initial position of the ith element in the heap } for (i=n/2; i>=1; i--) heapify(i,q); return q; } int dijkstra(int source,int target,int nverts) { int dist[nverts+1], i, v, w; HEAPMIN *heap; EDGE *adj; // init heap for(i=0;i <= nverts; i++) dist[i] = INFTY; dist[source]=0; heap = build_heap_min(dist,nverts); while((v = extractMin(heap))!= target) { adj = ADJS(Graph[v]); while(adj != NULL) { w = DEST(adj); if (dist[w] > dist[v]+WEIGHT(adj)) { dist[w] = dist[v]+WEIGHT(adj); decreaseKey(w,dist[w],heap); } adj = NXTADJ(adj); } } return dist[target]; } #ifdef DEBUG int weight_edge(int s,int t) { EDGE *edge = ADJS(Graph[s]); while (edge != NULL && DEST(edge) != t) edge = NXTADJ(edge); if (edge == NULL) { fprintf(stderr,"Error in the graph?\n"); exit(EXIT_FAILURE); } return WEIGHT(edge); } void checksol(int nargs,char *args[]) { FILE *f; int ntrips, length, d, lixo, nt, x, y, i; if (nargs > 1) { f = fopen(args[1],"r"); fscanf(f,"%d%d%d%d", &lixo,&lixo,&lixo,&ntrips); for(i=0; i< ntrips; i++) { length = 0; fscanf(f,"%d%d%d", &d,&nt,&x); while(--nt > 0) { fscanf(f,"%d", &y); length += weight_edge(x,y); x = y; } if (length%13 != d) { fprintf(stderr,"Error: trip %d: d = %d length = %d\n",i+1,d,length); exit(EXIT_FAILURE); } else fprintf(stderr,"Ok trip %d\n",i+1); } } } #endif int main(int nargs,char *args[]) { int n,alice,hole,ntrips; scanf("%d%d%d%d", &n,&alice,&hole,&ntrips); find_graph(n,ntrips); #ifdef DEBUG checksol(nargs,args); #endif printf("%d\n",dijkstra(alice,hole,n)); return 0; }