Título: Dados n puntos, encuentre la ruta más corta de s a t, de los cuales hay dos formas (se pueden mezclar): una es tomar el borde dirigido m dado (ui, vi, wi); la otra La especie puede ser de cualquier punto x a cualquier punto y, y su costo es c ∗ (x xor y)
El método de construcción simple es O (n ^ 2 + m). Sin embargo, de hecho, un borde con un peso de x-> y puede ser reemplazado por otros bordes, podemos dividir x en binario, un bit por uno La modificación finalmente alcanza y, y el peso pasado en este momento obviamente también es w.
Por ejemplo:
Supongamos que queremos pasar de 001 (2) a 010 (2), necesitamos gastar 2 ^ 0 + 2 ^ 1; sin embargo, el camino más corto tiene una naturaleza superior, podemos desmontar el borde, puede comenzar con De 001 (2) a 000 (2), y luego de 000 (2) a 010 (2), el costo es el mismo.
Es decir, para un punto x, solo necesitamos conectarlo a x * 2 ^ k, para que esté optimizado a O (nlogn + m), simplemente ejecute dij nuevamente.
Código:
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 #include <queue> 6 #include <cmath> 7 usando el espacio de nombres std; 8 int n, m, c, st, sd, x, y, val; 9 struct node { 10 int to, next, w; 11 } ed [ 5000005 ]; 12 int dis [ 5000005 ], vis [ 5000005 ], cabeza [ 5000005 ], cnt; 13 inid void add (int u, int v, int w) { 14 ed [++ cnt] .next = head [u]; 15 ed [cnt] .to = v; 16 ed [cnt] .w = w; 17 cabeza [u] = cnt; 18 } 19 en línea int read () { 20 int x = 1 , a = 0 ; 21 char ch = getchar (); 22 while (ch < ' 0 ' || ch> ' 9 ' ) { 23 if (ch ==' - ' ) x = - 1 ; 24 ch = getchar (); 25 } 26 while (ch <= ' 9 ' && ch> = ' 0 ' ) { 27 a = a * 10 + ch - ' 0 ' ; 28 ch = getchar (); 29 } 30 retorno x * a; 31 } 32 priority_queue <par < int , int >> q; 33inline void Dij ( int s) { 34 q.push (make_pair ( 0 , s)); memset (vis, 0 , sizeof (vis)); memset (dis, 63 , sizeof (dis)); dis [s] = 0 ; 35 while (! Q.empty ()) { 36 int x = q.top (). Second; 37 q.pop (); 38 if (vis [x]) continuar ; 39 vis [x] = 1 ; 40 para (registro int i = head [x]; i; i = ed [i] .next) { 41 int to = ed [i] .to; 42 if (dis [to]> dis [x] + ed [i] .w) { 43 dis [to] = dis [x] + ed [i] .w; 44 q.push (make_pair (- dis [to], to)); 45 } 46 } 47 } 48 regreso ; 49 } 50 int main () { 51 n = read (); m = read (); c = read (); 52 para ( int i = 1 ; i <= m; i ++ ) { 53 x = read (), y = read (), val =leer(); 54 sumar (x, y, val); 55 } 56 int lgn = piso (log2 (n)) + 1 ; 57 n = ( 1 << lgn) - 1 ; 58 para (registro int i = 1 ; i <= n; i ++ ) 59 para (registro int j = 0 ; j <lgn; j ++ ) 60 add (i, i ^ ( 1 << j), ( 1 << j ) * c); 61 st = leer (), sd = leer (); 62 Dij (st); 63 cout << dis [sd]; 64 }