zoukankan      html  css  js  c++  java
  • 多源最短路径算法

    本博客的代码的思想和图片参考:好大学慕课浙江大学陈越老师、何钦铭老师的《数据结构》

     多源最短路径算法

    1.使用Dijkstra算法对每个顶点运行一次运算,可以得到每个顶点到最图所有顶点的最小值,时间复杂度为:T = O( |V| 3 + |E||V|)。该算法对稀疏图比较好

    2.使用Floyd算法,时间复杂度为:T = O( |V| 3 ),该算法对稠密图比较好



    下面介绍Floyd算法

    D k [i][j] = 路径{ i --> { l --> k } --> j }的最小长度

    D 0 , D 1 , ..., D |V|-1 [i][j]即给出了ij的真正最短距离

    最初的D -1 是什么?

    D k-1 已经完成,递推到D k :

    或者k 属于最短路径{ i --> { l --> k } --> j },D k = D k-1

    或者k 属于最短路径{ i --> { l --> k } --> j },则该路径必定由两

    段最短路径组成: D k [i][j]=D k-1 [i][k]+D k-1 [k][j]



    void Floyd()

    { for ( i = 0; i < N; i++ )

    for( j = 0; j < N; j++ ) {

    D[i][j] = G[i][j];

    path[i][j] = -1;

    }

    for( k = 0; k < N; k++ )

    for( i = 0; i < N; i++ )

    for( j = 0; j < N; j++ )

    if( D[i][k] + D[k][j] < D[i][j] ) {

    D[i][j] = D[i][k] + D[k][j];

    path[i][j] = k;

    }

    }

      1 /*
      2  * floyd.c
      3  *
      4  *  Created on: 2017年5月14日
      5  *      Author: ygh
      6  */
      7 #include <stdio.h>
      8 #include <stdlib.h>
      9 
     10 #define MAX_VERTEX_NUM 100 /*define the max number of the vertex*/
     11 #define INFINITY 65535     /*define double byte no negitive integer max number is 65535*/
     12 #define ERROR -1
     13 
     14 typedef int vertex; /*define the data type of the vertex*/
     15 typedef int weightType; /*define the data type of the weight*/
     16 typedef char dataType; /*define the data type of the vertex value*/
     17 
     18 /*define the data structure of the Edge*/
     19 typedef struct eNode *ptrToENode;
     20 typedef struct eNode {
     21     vertex v1, v2; /*two vertex between the edge <v1,v2>*/
     22     weightType weight; /*the value of the edge's weight */
     23 };
     24 typedef ptrToENode edge;
     25 
     26 /*define the data structure of the graph*/
     27 typedef struct gNode *ptrToGNode;
     28 typedef struct gNode {
     29     int vertex_number; /*the number of the vertex*/
     30     int edge_nunber; /*the number of the edge*/
     31     weightType g[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; /*define the adjacent matrix weight of graph*/
     32     dataType data[MAX_VERTEX_NUM]; /*define the dataType array to store the value of vertex*/
     33 };
     34 typedef ptrToGNode adjacentMatrixGraph; /*a graph show by adjacent matrix*/
     35 
     36 /*
     37  create a graph given the vertex number.
     38  @param vertexNum The verter number of the graph
     39  @return a graph with vertex but no any egdgs
     40  */
     41 adjacentMatrixGraph createGraph(int vertexNum) {
     42     vertex v, w;
     43     adjacentMatrixGraph graph;
     44     graph = (adjacentMatrixGraph) malloc(sizeof(struct gNode));
     45     graph->vertex_number = vertexNum;
     46     graph->edge_nunber = 0;
     47     /*initialize the adjacent matrix*/
     48     for (v = 0; v < graph->vertex_number; v++) {
     49         for (w = 0; w < graph->vertex_number; w++) {
     50             graph->g[v][w] = INFINITY;
     51         }
     52     }
     53 
     54     return graph;
     55 }
     56 
     57 /*
     58  insert a edge to graph.We will distinct oriented graph and undirected graph
     59  @param graph The graph you want to insert edge
     60  @param e The edge you want to insert the graph
     61  @param isOriented Whether the graph is oriented graph.If the graph is oriented
     62  we will set adjacent matrix [n][m]=[m][n]=edge's weight,else we only set
     63  the adjacent matrix [n][m]=edge's weight
     64  */
     65 void inserEdge(adjacentMatrixGraph graph, edge e, int isOriented) {
     66     graph->g[e->v1][e->v2] = e->weight;
     67     if (!isOriented) {
     68         graph->g[e->v2][e->v1] = e->weight;
     69     }
     70 }
     71 
     72 /*
     73  construct a graph according user's input
     74 
     75  @return a graph has been filled good
     76  */
     77 adjacentMatrixGraph buildGraph(int isOrdered) {
     78     adjacentMatrixGraph graph;
     79     edge e;
     80     vertex i;
     81     int vertex_num;
     82     scanf("%d", &vertex_num);
     83     graph = createGraph(vertex_num);
     84     scanf("%d", &(graph->edge_nunber));
     85     if (graph->edge_nunber) {
     86         e = (edge) malloc(sizeof(struct eNode));
     87         for (i = 0; i < graph->edge_nunber; i++) {
     88             scanf("%d %d %d", &e->v1, &e->v2, &e->weight);
     89             e->v1--;
     90             e->v2--;
     91             inserEdge(graph, e, isOrdered);
     92         }
     93     }
     94     return graph;
     95 
     96 }
     97 
     98 /*
     99  * Floyd algorithms:
    100  1.D k [i][j] = 路径{ i --> { l -->  k } -->  j }的最小长度
    101  2.D 0 , D 1 , ..., D |V|-1 [i][j]即给出了i到j的真正最短距离
    102  3.最初的D -1 是什么?
    103  4.当D k-1 已经完成,递推到D k 时:
    104  或者k 属于最短路径{ i -->  { l -->  k } --> j },则D k = D k-1
    105  或者k 属于最短路径{ i -->  { l -->  k } -->  j },则该路径必定由两
    106  段最短路径组成: D k [i][j]=D k1 [i][k]+D k1 [k][j]
    107  *@param graph A graph store by adjacent matrix
    108  *@param d A two-dimensional array to store the distance value
    109  *@param path A two-dimensional array to store the path
    110  */
    111 int floyd(adjacentMatrixGraph graph, weightType d[][MAX_VERTEX_NUM],
    112         vertex path[][MAX_VERTEX_NUM]) {
    113     vertex i, j, k;
    114     /*
    115      * Initialize array
    116      */
    117     for (i = 0; i < graph->vertex_number; i++) {
    118         for (j = 0; j < graph->vertex_number; j++) {
    119             d[i][j] = graph->g[i][j];
    120             path[i][j] = -1;
    121         }
    122     }
    123     for (k = 0; k < graph->vertex_number; k++) {
    124         for (i = 0; i < graph->vertex_number; i++) {
    125             for (j = 0; j < graph->vertex_number; j++) {
    126                 if (d[i][k] + d[k][j] < d[i][j]) {
    127                     d[i][j] = d[i][k] + d[k][j];
    128                     /*
    129                      * Find negative circle
    130                      */
    131                     if (i == j && d[i][j] < 0) {
    132                         return 0;
    133                     }
    134                     path[i][j] = k;
    135                 }
    136             }
    137         }
    138     }
    139     return 1;
    140 }
    141 
    142 /*
    143  * Print the distance matrix
    144  */
    145 void toStringDistance(int d[MAX_VERTEX_NUM][MAX_VERTEX_NUM], int length) {
    146     vertex i, j;
    147     for (i = 0; i < length; i++) {
    148         printf("%d:", i);
    149         for (j = 0; j < length; j++) {
    150             printf("%d ", d[i][j]);
    151         }
    152         printf("
    ");
    153     }
    154 }
    155 
    156 /*
    157  * Print the path from source to destination
    158  * we will recursive method to print the path
    159  * 1.find the k between source and destination
    160  * 2.find point between source and k and recursive this method until there no points between them
    161  * 3.find the point between k and destination and recursive this method until there no points between them
    162  * @param source The index of the source point
    163  * @param destination The index of the destination
    164  * @param path A two-dimensional array to store the path
    165  */
    166 void toStringPath(int source, int destination, vertex path[][MAX_VERTEX_NUM]) {
    167     if (destination == -1 || source == -1) {
    168         return;
    169     } else {
    170         toStringPath(source, path[source][destination], path);
    171         if (path[source][destination] != -1) {
    172             printf("%d ", path[source][destination]);
    173         }
    174         toStringPath(path[source][destination], destination, path);
    175     }
    176 
    177 }
    178 
    179 /*
    180  * A test method
    181  */
    182 int main() {
    183     adjacentMatrixGraph graph = buildGraph(1);
    184     int d[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
    185     int path[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
    186     int source = 1;
    187     int destination = 5;
    188     floyd(graph, d, path);
    189     printf("toDistance
    ");
    190     toStringDistance(d, graph->vertex_number);
    191     printf("toPath:");
    192     printf("%d ", source);
    193     toStringPath(source, destination, path);
    194     printf("%d", destination);
    195     return 0;
    196 }
    Floyd

    下面是一个练习题:

    哈利·波特要考试了,他需要你的帮助。这门课学的是用魔咒将一种动物变成另一种动物的本事。例如将猫变成老鼠的魔咒是haha,将老鼠变成鱼的魔咒是hehe等等。反方向变化的魔咒就是简单地将原来的魔咒倒过来念,例如ahah可以将老鼠变成猫。另外,如果想把猫变成鱼,可以通过念一个直接魔咒lalala,也可以将猫变老鼠、老鼠变鱼的魔咒连起来念:hahahehe。

    现在哈利·波特的手里有一本教材,里面列出了所有的变形魔咒和能变的动物。老师允许他自己带一只动物去考场,要考察他把这只动物变成任意一只指定动物的本事。于是他来问你:带什么动物去可以让最难变的那种动物(即该动物变为哈利·波特自己带去的动物所需要的魔咒最长)需要的魔咒最短?例如:如果只有猫、鼠、鱼,则显然哈利·波特应该带鼠去,因为鼠变成另外两种动物都只需要念4个字符;而如果带猫去,则至少需要念6个字符才能把猫变成鱼;同理,带鱼去也不是最好的选择。

    输入格式:

    输入说明:输入第1行给出两个正整数NNN (≤100le 100100)和MMM,其中NNN是考试涉及的动物总数,MMM是用于直接变形的魔咒条数。为简单起见,我们将动物按1~NNN编号。随后MMM行,每行给出了3个正整数,分别是两种动物的编号、以及它们之间变形需要的魔咒的长度(≤100le 100100),数字之间用空格分隔。

    输出格式:

    输出哈利·波特应该带去考场的动物的编号、以及最长的变形魔咒的长度,中间以空格分隔。如果只带1只动物是不可能完成所有变形要求的,则输出0。如果有若干只动物都可以备选,则输出编号最小的那只。

    输入样例:

    6 11
    3 4 70
    1 2 1
    5 4 50
    2 6 50
    5 6 60
    1 3 70
    4 6 60
    3 6 80
    5 1 100
    2 4 60
    5 2 80
    

    输出样例:

    4 70
    
      1 /*
      2  * harrypot.c
      3  *
      4  *  Created on: 2017年5月14日
      5  *      Author: ygh
      6  */
      7 #include <stdio.h>
      8 #include <stdlib.h>
      9 
     10 #define MAX_VERTEX_NUM 100 /*define the max number of the vertex*/
     11 #define INFINITY 65535     /*define double byte no negitive integer max number is 65535*/
     12 #define ERROR -1
     13 
     14 typedef int vertex; /*define the data type of the vertex*/
     15 typedef int weightType; /*define the data type of the weight*/
     16 typedef char dataType; /*define the data type of the vertex value*/
     17 
     18 /*define the data structure of the Edge*/
     19 typedef struct eNode *ptrToENode;
     20 typedef struct eNode {
     21     vertex v1, v2; /*two vertex between the edge <v1,v2>*/
     22     weightType weight; /*the value of the edge's weight */
     23 };
     24 typedef ptrToENode edge;
     25 
     26 /*define the data structure of the graph*/
     27 typedef struct gNode *ptrToGNode;
     28 typedef struct gNode {
     29     int vertex_number; /*the number of the vertex*/
     30     int edge_nunber; /*the number of the edge*/
     31     weightType g[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; /*define the adjacent matrix weight of graph*/
     32     dataType data[MAX_VERTEX_NUM]; /*define the dataType array to store the value of vertex*/
     33 };
     34 typedef ptrToGNode adjacentMatrixGraph; /*a graph show by adjacent matrix*/
     35 
     36 /*
     37  create a graph given the vertex number.
     38  @param vertexNum The verter number of the graph
     39  @return a graph with vertex but no any egdgs
     40  */
     41 adjacentMatrixGraph createGraph(int vertexNum) {
     42     vertex v, w;
     43     adjacentMatrixGraph graph;
     44     graph = (adjacentMatrixGraph) malloc(sizeof(struct gNode));
     45     graph->vertex_number = vertexNum;
     46     graph->edge_nunber = 0;
     47     /*initialize the adjacent matrix*/
     48     for (v = 0; v < graph->vertex_number; v++) {
     49         for (w = 0; w < graph->vertex_number; w++) {
     50             graph->g[v][w] = INFINITY;
     51         }
     52     }
     53 
     54     return graph;
     55 }
     56 
     57 /*
     58  insert a edge to graph.We will distinct oriented graph and undirected graph
     59  @param graph The graph you want to insert edge
     60  @param e The edge you want to insert the graph
     61  @param isOriented Whether the graph is oriented graph.If the graph is oriented
     62  we will set adjacent matrix [n][m]=[m][n]=edge's weight,else we only set
     63  the adjacent matrix [n][m]=edge's weight
     64  */
     65 void inserEdge(adjacentMatrixGraph graph, edge e, int isOriented) {
     66     graph->g[e->v1][e->v2] = e->weight;
     67     if (!isOriented) {
     68         graph->g[e->v2][e->v1] = e->weight;
     69     }
     70 }
     71 
     72 /*
     73  construct a graph according user's input
     74 
     75  @return a graph has been filled good
     76  */
     77 adjacentMatrixGraph buildGraph(int isOrdered) {
     78     adjacentMatrixGraph graph;
     79     edge e;
     80     vertex i;
     81     int vertex_num;
     82     scanf("%d", &vertex_num);
     83     graph = createGraph(vertex_num);
     84     scanf("%d", &(graph->edge_nunber));
     85     if (graph->edge_nunber) {
     86         e = (edge) malloc(sizeof(struct eNode));
     87         for (i = 0; i < graph->edge_nunber; i++) {
     88             scanf("%d %d %d", &e->v1, &e->v2, &e->weight);
     89             e->v1--;
     90             e->v2--;
     91             inserEdge(graph, e, isOrdered);
     92         }
     93     }
     94     return graph;
     95 
     96 }
     97 
     98 int floyd(adjacentMatrixGraph graph, weightType d[][MAX_VERTEX_NUM],
     99         vertex path[][MAX_VERTEX_NUM]) {
    100     vertex i, j, k;
    101     /*
    102      * Initialize array
    103      */
    104     for (i = 0; i < graph->vertex_number; i++) {
    105         for (j = 0; j < graph->vertex_number; j++) {
    106             d[i][j] = graph->g[i][j];
    107             path[i][j] = -1;
    108         }
    109     }
    110     for (k = 0; k < graph->vertex_number; k++) {
    111         for (i = 0; i < graph->vertex_number; i++) {
    112             for (j = 0; j < graph->vertex_number; j++) {
    113                 if (d[i][k] + d[k][j] < d[i][j]) {
    114                     d[i][j] = d[i][k] + d[k][j];
    115                     /*
    116                      * Find negative circle
    117                      */
    118                     if (i == j) {
    119                         d[i][j] = INFINITY;
    120                     }
    121                     path[i][j] = k;
    122                 }
    123             }
    124         }
    125     }
    126     return 1;
    127 }
    128 
    129 void toStringDistance(int d[MAX_VERTEX_NUM][MAX_VERTEX_NUM], int length) {
    130     vertex i, j;
    131     for (i = 0; i < length; i++) {
    132         printf("%d:", i);
    133         for (j = 0; j < length; j++) {
    134             printf("%d ", d[i][j]);
    135         }
    136         printf("
    ");
    137     }
    138 }
    139 
    140 /*
    141  * Algorithms thoughts:
    142  * choose the max value expect for 65535 then sore a array,then find the
    143  * minimal value from the array and the index
    144  */
    145 void selectAnnimal(int d[MAX_VERTEX_NUM][MAX_VERTEX_NUM], int length) {
    146     vertex i, j;
    147     int maxValue = -1;
    148     int minValue = 65535;
    149     int key = 0;
    150     int arr[length];
    151     for (i = 0; i < length; i++) {
    152         maxValue = -1;
    153         for (j = 0; j < length; j++) {
    154             if (d[i][j] > maxValue && i != j) {
    155                 maxValue = d[i][j];
    156             }
    157         }
    158         if (maxValue == INFINITY) {
    159             printf("0
    ");
    160             return;
    161         } else {
    162             arr[i] = maxValue;
    163         }
    164     }
    165 
    166     for (i = 0; i < length; i++) {
    167         if (arr[i] < minValue) {
    168             key = i;
    169             minValue = arr[i];
    170         }
    171     }
    172 
    173     printf("%d %d", key + 1, minValue);
    174 }
    175 
    176 int main() {
    177     adjacentMatrixGraph graph = buildGraph(0);
    178     int d[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
    179     int path[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
    180     floyd(graph, d, path);
    181     selectAnnimal(d, graph->vertex_number);
    182     return 0;
    183 }
    HarryPot

    测试数据:

    6 11
    3 4 70
    1 2 1
    5 4 50
    2 6 50
    5 6 60
    1 3 70
    4 6 60
    3 6 80
    5 1 100
    2 4 60
    5 2 80

    输出样例:

    4 70




  • 相关阅读:
    Topshelf的使用
    ref和out的区别
    .NET编码解码(HtmlEncode与HtmlDecode)
    查询表中某字段有重复记录个数的方法
    ActiveReports 报表应用教程 (8)---交互式报表之动态过滤
    ActiveReports 报表应用教程 (7)---交叉报表及数据透视图实现方案
    ActiveReports 报表应用教程 (6)---分组报表
    ActiveReports 报表应用教程 (5)---解密电子商务领域首张电子发票的诞生(套打报表)
    ActiveReports 报表应用教程 (4)---分栏报表
    ActiveReports 9 新功能:借助目录(TOC)控件为报表添加目录功能
  • 原文地址:https://www.cnblogs.com/yghjava/p/6853790.html
Copyright © 2011-2022 走看看