Dij - P4366 [Código + # 4] El camino más corto

* Enviar

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 }

 

Supongo que te gusta

Origin www.cnblogs.com/very-beginning/p/12732809.html
Recomendado
Clasificación