基础图论复习之最短路

基础图论复习之最短路
最短路径算法复习:

Dijkstra算法

详细介绍
Dijkstra
复杂度是O(N^2),如果用binary heap优化可以达到O((E+N)logN),用fibonacci heap可以优化到O(NlogN+E)
其基本思想是采用贪心法,
对于每个节点v[i],维护估计最短路长度最大值,每次取出一个使得该估计值最小的t,并采用与t相连的边对其余点的估计值进行更新,更新后不再考虑t
在此过程中,估计值单调递减,所以可以得到确切的最短路。

 

Floyd-Warshall算法

详细介绍
Floyd
是计算每对点间最短路径(APSP)的经典算法。
时间复杂度是雷打不动的O(n^3)

*Floyd-Warshall算法的基本思想:

     它的基本思想就是动态规划。假设在一个图中有一条从结点A经过BCD到达E的路径是最短的,那么从ABCD的路径也分别是最短的。用反证法证明,假如AD的路径不是最短的,那么加上DE的路径长度必然比原来的所谓最短长度小,与假设矛盾。

     假设k点是结点ij的路径的一个中间结点,如果路径ik和路径kj都是最短路径,那么ik+kj组成的路径ij必然是最短路径。

     通过上面的观察,我们可以推出判断两点(设为ij)之间的最短路径其实是求出 ij直接相连的距离、i通过其他结点k到达j的距离(ik + kj)的最小值。

 

Bellman-Ford算法

详细介绍
Bellman-Ford
主要是用于负权图。Bellman-Ford算法即标号修正算法。
实践中常用到的方法通常是FIFO标号修正算法和一般标号修正算法的Dequeue实现。
前者最坏时间复杂度是O(nm), 是解决任意边权的单源最短路经问题的最优强多项式算法。
也可以用这个算法判断是否存在负权回路.

迭代算法的思想:不停地调整图中的顶点值(源点到该点的最短路径值),直到没有点的值调整了为止。

 

  • SPFA算法


Input:

6 1

0 50 10 0 45 0

0 0 15 0 10 0

20 0 0 15 0 0

0 20 0 0 35 0

0 0 0 30 0 0

0 0 0 3 0 0

1 4

Output:

25

1->3->4



Dijkstra:

 1  /*
 2   * Problem: 最短路
 3   * Author: Xu Fei
 4   * Time: 2010.8.1 15:30
 5   * Memo: Dijkstra
 6    */
 7 
 8  #include < iostream >
 9  #include < cstdio >
10  using   namespace  std;
11 
12  const   int  INF = 0xFFFFFFF ;
13 
14  int  N,M;
15  int  S[ 100 ];
16  int  T[ 100 ];
17  int  pre[ 100 ];
18  int  dis[ 100 ];
19  int  cost[ 100 ][ 100 ];
20  bool  vis[ 100 ];
21 
22  void  init()
23  {
24       int  i,j;
25      
26      scanf( " %d%d " , & N, & M);
27       for (i = 1 ;i <= N; ++ i)
28           for (j = 1 ;j <= N; ++ j)
29          {
30              scanf( " %d " , & cost[i][j]);
31               if (cost[i][j] == 0 )
32                  cost[i][j] = INF;
33          }
34       for (i = 1 ;i <= M; ++ i)
35          scanf( " %d%d " , & S[i], & T[i]);
36  }
37  int  dijkstra( int  s, int  t)
38  {
39       int  i,j,Min,kj;
40      
41       for (i = 1 ;i <= N; ++ i)
42      {
43          dis[i] = cost[s][i];
44          vis[i] = true ;
45          pre[i] = s;
46      }
47      dis[s] = 0 ; vis[s] = false ;
48       for (i = 1 ;i < N; ++ i)
49      {
50          Min = INF;
51           for (j = 1 ;j <= N; ++ j)
52               if (vis[j] && dis[j] < Min)
53                  Min = dis[j],kj = j;
54           if (kj == t)  break ;
55          vis[kj] = false ;
56           for (j = 1 ;j <= N; ++ j)
57               if (vis[j] && dis[j] > dis[kj] + cost[kj][j])
58              {
59                  dis[j] = dis[kj] + cost[kj][j];
60                  pre[j] = kj;
61              }
62      }
63       return  dis[t];
64  }
65  void  dfs( int  s, int  t)
66  {
67       if (s == t)
68          printf( " %d " ,s);
69       else
70      {
71          dfs(s,pre[t]);
72          printf( " ->%d " ,t);
73      }
74  }
75  void  solve()
76  {
77       int  i;
78      
79       for (i = 1 ;i <= M; ++ i)
80      {
81          printf( " %d\n " ,dijkstra(S[i],T[i]));
82          dfs(S[i],T[i]);
83          printf( " \n " );
84      }
85  }
86  int  main()
87  {
88      freopen( " zui.in " , " r " ,stdin);
89      freopen( " zui.out " , " w " ,stdout);
90      
91      init();
92      solve();
93       return   0 ;
94  }
95 


Floyd:

 1  /*
 2   * Problem: 最短路
 3   * Author: Xu Fei
 4   * Time: 2010.8.1 16.12
 5   * Method: Floyd
 6    */
 7   
 8  #include < iostream >
 9  #include < cstdio >
10  using   namespace  std;
11 
12  const   int  INF = 0xFFFFFFF ;
13 
14  int  N,M;
15  int  S[ 100 ];
16  int  T[ 100 ];
17  int  mid[ 100 ][ 100 ];
18  int  cost[ 100 ][ 100 ];
19 
20  void  init()
21  {
22       int  i,j;
23      
24      scanf( " %d%d " , & N, & M);
25       for (i = 1 ;i <= N; ++ i)
26           for (j = 1 ;j <= N; ++ j)
27          {
28              scanf( " %d " , & cost[i][j]);
29               if (i != j && cost[i][j] == 0 )
30                  cost[i][j] = INF;
31              mid[i][j] = 0 ;
32          }
33       for (i = 1 ;i <= M; ++ i)
34          scanf( " %d%d " ,S + i,T + i);
35  }
36  void  floyd()
37  {
38       int  i,j,k;
39      
40       for (k = 1 ;k <= N; ++ k)
41           for (i = 1 ;i <= N; ++ i) 
42               if (i != k)
43                for (j = 1 ;j <= N; ++ j)
44                    if (j != k && j != i)
45                       if (cost[i][j] > cost[i][k] + cost[k][j])
46                      {
47                          cost[i][j] = cost[i][k] + cost[k][j];
48                          mid[i][j] = k;
49                      }
50  }
51  void  dfs( int  s, int  t)
52  {
53       if (mid[s][t] == 0 return ;
54      dfs(s,mid[s][t]);
55      printf( " ->%d " ,mid[s][t]);
56      dfs(mid[s][t],t);
57  }
58  void  solve()
59  {
60       int  i;
61      
62      floyd();
63       for (i = 1 ;i <= M; ++ i)
64      {
65          printf( " %d\n " ,cost[S[i]][T[i]]);
66          printf( " %d " ,S[i]);
67          dfs(S[i],T[i]);
68          printf( " ->%d\n " ,T[i]);
69      }
70  }
71  int  main()
72  {
73      freopen( " zui.in " , " r " ,stdin);
74      freopen( " zui.out " , " w " ,stdout);
75      
76      in it ();
77      solve();
78       return   0 ;
79  }


Ford:

 1  /*
 2   * Problem: 最短路
 3   * Author: Xu Fei
 4   * Time: 2010.8.1 16.46
 5   * Method: Ford
 6    */
 7   
 8  #include < iostream >
 9  #include < cstdio >
10  using   namespace  std;
11 
12  const   int  INF = 0xFFFFFFF ;
13 
14  int  N,M;
15  bool  flag;
16  int  S[ 100 ];
17  int  T[ 100 ];
18  int  dis[ 100 ];
19  int  pre[ 100 ];
20  int  cost[ 100 ][ 100 ];
21 
22  void  in it ()
23  {
24       int  i,j;
25      
26      scanf( " %d%d " , & N, & M);
27       for (i = 1 ;i <= N; ++ i)
28           for (j = 1 ;j <= N; ++ j)
29          {
30              scanf( " %d " , & cost[i][j]);
31               if (i != j && cost[i][j] == 0 )
32                  cost[i][j] = INF;
33          }
34       for (i = 1 ;i <= M; ++ i)
35          scanf( " %d%d " ,S + i,T + i);
36  }
37  int  ford( int  s, int  t)
38  {
39       int  i,j;
40      
41       for (i = 1 ;i <= N; ++ i)
42      {
43          dis[i] = INF;
44          pre[i] = i;
45      }
46      dis[s] = 0 ;
47       do {
48          flag = false ;
49           for (i = 1 ;i <= N; ++ i)
50               if (dis[i] < INF)
51                   for (j = 1 ;j <= N; ++ j)
52                       if (dis[j] > dis[i] + cost[i][j])
53                      {
54                          dis[j] = dis[i] + cost[i][j];
55                          pre[j] = i;
56                          flag = true ;
57                      }
58      } while (flag);
59       return  dis[t];
60  }
61  void  dfs( int  s, int  t)
62  {
63       if (s == t)  return ;
64      dfs(s,pre[t]);
65      printf( " %d-> " ,pre[t]);
66  }
67  void  solve()
68  {
69       int  i;
70      
71       for (i = 1 ;i <= M; ++ i)
72      {
73          printf( " %d\n " ,ford(S[i],T[i]));
74          dfs(S[i],T[i]);
75          printf( " %d\n " ,T[i]);
76      }
77  }
78  int  main()
79  {
80      freopen( " zui.in " , " r " ,stdin);
81      freopen( " zui.out " , " w " ,stdout);
82      
83      in it ();
84      solve();
85       return   0 ;
86  }

你可能感兴趣的:(基础图论复习之最短路)