Dij--P4366 [コード+#4]最短経路

*送信

タイトル:与えられたn点から、sからtへの最短経路を見つけます。そのうちの2つの方法(混合可能)があります。1つは、指定されたmの有向エッジ(ui、vi、wi)を取ることです。種は任意の点xから任意の点yまでであり、そのコストはc ∗(x xor y)です。

単純な構築方法はO(n ^ 2 + m)ですが、実際には、x-> yの重みを持つエッジを他のエッジで置き換えることができ、xをバイナリに1ビットずつ分割できます。最終的に変更はyに到達し、このときに渡される重みも明らかにwです。

たとえば、次のとおりです。

001(2)から010(2)に移動する場合、2 ^ 0 + 2 ^ 1を費やす必要があります。ただし、最短パスは優れた性質を持っているため、エッジを分解できます。 001(2)から000(2)まで、次に000(2)から010(2)まで、コストは同じです。

つまり、点xの場合、彼をx * 2 ^ kに接続するだけでよいので、O(nlogn + m)に最適化され、再度dijを実行します。

コード:

1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <algorithm>
 5 #include <queue> 
 6 #include <cmath>
 7  名前空間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 ]、head [ 5000005 ]、cnt;
13インライン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      head [u] = cnt;
18  }
 19インラインint read(){
 20      int x = 1、a = 0 ;
21      文字 ch = getchar();
22      while(ch < ' 0 ' || ch> ' 9 ' ){
 23          if(ch ==' - ')x = -1 ;
24          ch = getchar();
25      }
 26      ながら、(CH <= ' 9 ' && CH> = ' 0 ' ){
 27          、A = A * 10 + CH - ' 0 ' 28          ch = getchar();
29      }
 30は      x * aを返します。
31  }
 32 priority_queue <pair < intint >> q;
33インラインvoid Dij(int s){
 34      q.push(make_pair(0、s)); memset(vis、0sizeof(vis)); memset(dis、63sizeof(dis)); dis [s] = 0 ;
35      while(!q.empty()){
 36          int x = q.top()。second;
37          q.pop();
38          であれば(VIS [X])続けます39          vis [x] = 1 ;
40          のために(登録int型 ; I iが= Iがヘッド= [X] {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      リターン;
49  }
 50  int main(){
 51      n = read(); m = read(); c = read();
52      forint i = 1 ; i <= m; i ++ ){
 53          x = read()、y = read()、val =読んだ();
54          add(x、y、val);
55      }
 56      int lgn = floor(log2(n))+ 1 ;
57      n =(1 << lgn)-1 ;
58     for register int i = 1 ; i <= n; i ++ 59          for(register int j = 0 ; j <lgn; j ++ 60              add(i、i ^(1 << j)、(1 << j )* c);
61      st = read()、sd = read();
62      Dij(st);
63     cout << dis [sd];
64 }

 

おすすめ

転載: www.cnblogs.com/very-beginning/p/12732809.html