zoukankan      html  css  js  c++  java
  • 最短路径问题

    Dijkstra算法:有权图的单源最短路

    1.最短路必定只经过S中的顶点

      如果还存在一个w在S之外,v0>w必定小于v0>v,但路径是按照递增顺序生成的,那么w一定已经收录了,与前提矛盾。    

    2.新收录一个v,会影响v的邻接点的dist值

      如果收录v使得s>w的路径变短,则s>w的路径一定经过v,并且v>w有一条边。如果v>w中间还存在顶点的话,该顶点一定在S之外(S是按递增顺序生成的,v刚被收录)而w的dist值为只经过S中的顶点。 dist[w] = min{dist[w], dist[v]+ <v, w>的权重}                                                                                                                             

    3.过程

      1.从V-S中找到dist[i]最小的下标i,收录到S中

      2.更新与i的邻接点的dist值 

      3.V==S时停止

    4.代码

     1 //邻接矩阵存储
     2 #define MaxVertexNum 1100
     3 struct GraphNode
     4 {
     5     int Nv;
     6     int Ne;
     7     int G[MaxVertexNum][MaxVertexNum];
     8 };
     9 typedef struct GraphNode *MGraph;
    10 
    11 Vertex FindMinDist(MGraph Graph, int dist[], int collected[])
    12 {
    13     Vertex MinV, V;
    14     int MinDist = INFINITY;
    15     
    16     for (V = 0; V < Graph->Nv; V++) {
    17         if (collected[V] == false && dist[V]<MinDist) //在未收录中找且dist[V]更小
    18         {
    19             MinDist = dist[V];
    20             MinV = V;
    21         }
    22     }
    23     if (MinDist < INFINITY)
    24         return MinV;
    25     else
    26         return ERROR;
    27 }
    28 
    29 bool Dijkstra(MGraph Graph, int dist[], int path[], Vertex s)
    30 {
    31     int collected[MaxVertexNum];
    32     Vertex v, w;
    33     
    34     for (v = 0; v < Graph->Nv; v++) {
    35         dist[v] = Graph->G[s][v];
    36         if (dist[v] < INFINITY)
    37             path[v] = s;
    38         else
    39             path[v] = -1;
    40         collected[v] = false;
    41     }
    42     dist[v] = 0;
    43     collected[s] = true;
    44     
    45     while (1) {
    46         v = FindMinDist(Graph, dist, collected);
    47         if (v == ERROR)
    48             break;  //全收录完
    49         collected[v] = true;
    50         for (w = 0; w < Graph->Nv; w++) {
    51             if (collected[w] == false && Graph->G[v][w]<INFINITY) {
    52                 if (Graph->G[v][w] < 0)  //负值圈
    53                     return false;
    54                 if (dist[v]+Graph->G[v][w] < dist[w]) {
    55                     dist[w] = dist[v] + Graph->G[v][w];
    56                     path[w] = v;
    57                 }
    58             }
    59         }
    60     }
    61     return true;
    62 }

    5.时间复杂度

      直接扫描所有未收录的顶点 T = O(|V|^2 + |E|)   稠密图效果好

      若用最小堆存取dist 读取最小的并更新堆O(log|V|), 但更新dist[w]的值需要插入最小堆O(log|V|)  T = O(|V|log|V| + |E|log|V|) = O(|E|log|V|)  稀疏图较好 (E和V同一个数量级,|V|log|V|比|V|^2要好)

    若将单源最短路算法调用|V|遍,对于稠密图T = O(|V|^3 + |E||V|) 对于稀疏图较好

    对于稠密图有Floyd算法 

    Floyd算法:多源最短路算法

    采用DP思想

    D_{{i,j,k}}为从ij的只以(1..k)集合中的节点为中间节点的最短路径的长度。

    1. 若最短路径经过点k,则D_{{i,j,k}}=D_{{i,k,k-1}}+D_{{k,j,k-1}}
    2. 若最短路径不经过点k,则D_{{i,j,k}}=D_{{i,j,k-1}}

    因此,D_{{i,j,k}}={mbox{min}}(D_{{i,j,k-1}},D_{{i,k,k-1}}+D_{{k,j,k-1}})

     1 //邻接矩阵存储
     2 
     3 bool Floyd(MGraph Graph, WeightType D[][MaxVertexNum], Vertex path[])
     4 {
     5     Vertex i, j, k;
     6     
     7     for (i = 0; i < Graph->Nv; i++)
     8     for (j = 0; j < Graph->Nv; j++) {
     9         D[i][j] = Graph->G[i][j];
    10         path[i][j] = -1;
    11     }
    12     
    13     for (k = 0; k < Graph->Nv; k++)
    14         for (i = 0; i < Graph->Nv; i++)
    15             for (j = 0; j < Graph->Nv; j++)
    16                 if (D[i][k] + D[k][j] < D[i][j]) 
    17                 {
    18                     D[i][j] = D[i][k] + D[k][j];
    19                     if (i == j && D[i][j] < 0)
    20                         return false;
    21                     path[i][j] = k;
    22                 }
    23     return true;
    24 }

    输出路径:

      递归输出, 先输出i到k,再输出k,再输出k到j路线。

    时间复杂度

      T = O(|V|^3)

     

  • 相关阅读:
    int 类型 占多少字节是由什么决定的
    layer.js漂亮的弹出框
    jquery分页点击后页面置顶
    动态请求页面生成静态页
    弹出ifame页面(jquery.reveal.js)
    Request.QueryString["id"] 、Request.Params["id"] 的强大
    为什么现在改用int.TryParse了
    时间格式(例如:2015-11-09)
    返回前一页
    sql获得某个时间段的数据
  • 原文地址:https://www.cnblogs.com/whileskies/p/6815998.html
Copyright © 2011-2022 走看看