求c++ 程序 网络上两点间的最短路径

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了求c++ 程序 网络上两点间的最短路径相关的知识,希望对你有一定的参考价值。

一、实验要求
掌握有向图和网络的邻接矩阵表示法。
掌握Dijkstra算法。
能够根据Dijkstra算法编写相应的程序,对于网络中给定的一点,能够计算这点到网络其他各点间的最短路径长度。
具体要求:对于一个以邻接矩阵给出的网,计算出任意给定的两点间的最短路经。邻接矩阵用n行n列的数据形式给出,“-1”或空表示两个节点间无路径。

周三后问题作废。。。

能直接运行的加分

/*
* File: shortest.c
* Description: 网络中两点最短路径 Dijkstra 算法
* Shortest Path Dijkstra Algorithm
* Created: 2001/11/25
* Author: Justin Hou [mailto:justin_hou@hotmail.com]
*/

#include <stdio.h>
#define true 1
#define false 0
#define I 9999 /* 无穷大 */
#define N 20 /* 城市顶点的数目 */

int cost[N][N] =
0,3,I,I,I,1,I,I,I,I,I,I,I,I,I,I,I,I,I,I,
3,0,5,I,I,I,6,I,I,I,I,I,I,I,I,I,I,I,I,I,
I,5,0,4,I,I,I,1,I,I,I,I,I,I,I,I,I,I,I,I,
I,I,4,0,2,I,I,I,6,I,I,I,I,I,I,I,I,I,I,I,
I,I,I,2,0,I,I,I,I,7,I,I,I,I,I,I,I,I,I,I,
1,I,I,I,I,0,1,I,I,I,2,I,I,I,I,I,I,I,I,I,
I,6,I,I,I,1,0,6,I,I,I,7,I,I,I,I,I,I,I,I,
I,I,1,I,I,I,6,0,2,I,I,I,3,I,I,I,I,I,I,I,
I,I,I,6,I,I,I,2,0,8,I,I,I,4,I,I,I,I,I,I,
I,I,I,I,7,I,I,I,8,0,I,I,I,I,5,I,I,I,I,I,
I,I,I,I,I,2,I,I,I,I,0,4,I,I,I,3,I,I,I,I,
I,I,I,I,I,I,7,I,I,I,4,0,3,I,I,I,4,I,I,I,
I,I,I,I,I,I,I,3,I,I,I,3,0,3,I,I,I,5,I,I,
I,I,I,I,I,I,I,I,4,I,I,I,3,0,7,I,I,I,2,I,
I,I,I,I,I,I,I,I,I,5,I,I,I,7,0,I,I,I,I,3,
I,I,I,I,I,I,I,I,I,I,3,I,I,I,I,0,5,I,I,I,
I,I,I,I,I,I,I,I,I,I,I,4,I,I,I,5,0,8,I,I,
I,I,I,I,I,I,I,I,I,I,I,I,5,I,I,I,8,0,6,I,
I,I,I,I,I,I,I,I,I,I,I,I,I,2,I,I,I,6,0,4,
I,I,I,I,I,I,I,I,I,I,I,I,I,I,3,I,I,I,4,0
;
int dist[N]; /* 存储当前最短路径长度 */
int v0 = 'A' - 65; /* 初始点是 A */

void main()

int final[N], i, v, w, min;

/* 初始化最短路径长度数据,所有数据都不是最终数据 */
for (v = 0; v < N; v++)
final[v] = false;
dist[v] = cost[v0][v];


/* 首先选v0到v0的距离一定最短,最终数据 */
final[v0] = true;

/* 寻找另外 N-1 个结点 */
for (i = 0; i < N-1; i++)
min = I; /* 初始最短长度无穷大 */

/* 寻找最短的边 */
for (w = 0; w < N; w++)
if (!final[w] && dist[w] < min)
min = dist[w];
v = w;


final[v] = true; /* 加入新边 */

for (w = 0; w < N; w++) /* 更新 dist[] 数据 */
if (!final[w] && dist[v] + cost[v][w] < dist[w])
dist[w] = dist[v] + cost[v][w];




for (i = 0; i < N; i++) /* 显示到监视器 */
printf("%c->%c: %2d\t", v0 + 65, i + 65, dist[i]);

);
if (left == NULL || right == NULL)
fprintf(stderr,"Error malloc.\n");
exit(-1);

/* 初始化左右分枝结点 */
left->bound = root.bound; /* 继承父结点的下界 */
left->matrix = LeftNode(root.matrix, selectedEdge); /* 删掉分枝边 */
left->path = root.path; /* 继承父结点的路径,没有增加新边 */
left->left = NULL;
left->right = NULL;

right->bound = root.bound;
right->matrix = RightNode(root.matrix, selectedEdge, root.path);/* 删除行列和回路边 */
right->path = AddEdge(selectedEdge, root.path); /* 加入所选边 */
right->left = NULL;
right->right = NULL;

/* 归约左右分枝结点 */
left->bound += Simplify(&left->matrix);
right->bound += Simplify(&right->matrix);

/* 链接到根 */
root.left = left;
root.right = right;

/* 显示到监视器 */
puts("Right Branch:\n------------");
ShowMatrix(right->matrix);
puts("Left Branch:\n-----------");
ShowMatrix(left->matrix);

/* 如果右结点下界小于当前最佳答案,继续分枝搜索 */
if (right->bound < minDist)
BABA(*right);

/* 否则不搜索,因为这条枝已经不可能产生更佳路线 */
else
printf("Current minDist is %d, ", minDist);
printf("Right Branch's Bound(= %d).\n", right->bound);
printf("This branch is dead.\n");


/* 如果右结点下界小于当前最佳答案,继续分枝搜索 */
if (left->bound < minDist)
BABA(*left);

/* 否则不搜索,因为这条枝已经不可能产生更佳路线 */
else
printf("Current minDist is %d, ", minDist);
printf("Left Branch's Bound(= %d).\n", left->bound);
printf("This branch is dead.\n");


printf("The best answer now is %d\n", minDist);
return (minPath);


/* 修补路径 */
PATH MendPath(PATH path, MATRIX c)

int row, col;
EDGE edge;
int n = c.citiesNumber;

for (row = 0; row < n; row++)
edge.head = row;
for (col = 0; col < n; col++)
edge.tail = col;
if (c.distance[row][col] == 0)
path = AddEdge(edge, path);



return path;



/* 归约费用矩阵,返回费用矩阵的归约常数 */
int Simplify(MATRIX* c)

int row, col, min_dist, h;
int n = c->citiesNumber;

h = 0;
/* 行归约 */
for (row = 0; row < n; row++)
/* 找出本行最小的元素 */
min_dist = INFINITY;
for (col = 0; col < n; col++)
if (c->distance[row][col] < min_dist)
min_dist = c->distance[row][col];


/* 如果本行元素都是无穷,说明本行已经被删除 */
if (min_dist == INFINITY) continue;
/* 本行每元素减去最小元素 */
for (col = 0; col < n; col++)
if (c->distance[row][col] != INFINITY)
c->distance[row][col] -= min_dist;


/* 计算归约常数 */
h += min_dist;


/* 列归约 */
for (col = 0; col < n; col++)
/* 找出本列最小的元素 */
min_dist = INFINITY;
for (row = 0; row < n; row++)
if (c->distance[row][col] < min_dist)
min_dist = c->distance[row][col];


/* 如果本列元素都是无穷,说明本列已经被删除 */
if (min_dist == INFINITY) continue;
/* 本列元素减去最小元素 */
for (row = 0; row < n; row++)
if (c->distance[row][col] != INFINITY)
c->distance[row][col] -= min_dist;


/* 计算归约常数 */
h += min_dist;

return (h);


/* 搜索所有花费为零的边中最合适的,使左枝下界更大 */
EDGE SelectBestEdge(MATRIX c)

int row, col;
int n = c.citiesNumber;
int maxD;
EDGE best, edge;

/* 所用函数声明 */
int D(MATRIX, EDGE);

maxD = 0;
for (row = 0; row < n; row++)
for (col = 0; col < n; col++)
edge.head = row;
edge.tail = col;
if (!c.distance[row][col] && maxD < D(c, edge))
maxD = D(c, edge);
best = edge;



return (best);


/* 计算如果选 edge 作为分枝边,左枝(不含 edge)下界的增量 */
int D(MATRIX c, EDGE edge)

int row, col, dRow, dCol;
int n = c.citiesNumber;

dRow = INFINITY;
for (col = 0; col < n; col++)
if (dRow < c.distance[edge.head][col] && col != edge.tail)
dRow = c.distance[edge.head][col];


dCol = INFINITY;
for (row = 0; row < n; row++)
if (dCol < c.distance[row][edge.tail] && row != edge.head)
dCol = c.distance[row][edge.tail];


return (dRow + dCol);


/* 删掉所选分枝边 */
MATRIX LeftNode(MATRIX c, EDGE edge)

c.distance[edge.head][edge.tail] = INFINITY;
return c;


/* 删除行列和回路边后的矩阵 */
MATRIX RightNode(MATRIX c, EDGE edge, PATH path)

int row, col;
int n = c.citiesNumber;
EDGE loopEdge;

/* 声明所需要的求回路边函数 */
EDGE LoopEdge(PATH, EDGE);

for (col = 0; col < n; col++)
c.distance[edge.head][col] = INFINITY;
for (row = 0; row < n; row++)
c.distance[row][edge.tail] = INFINITY;

loopEdge = LoopEdge(path, edge);
c.distance[loopEdge.head][loopEdge.tail] = INFINITY;

return (c);


/* 计算回路边的函数
* 除了加入的新边, 当前结点路线集合中还可能包含一些已经选定的边, 这些边构成一条或
* 几条路径, 为了不构成回路, 必须使其中包含新边的路径头尾不能相连,本函数返回这个
* 头尾相连的边,以便把这个回路边的长度设成无穷。
*/
EDGE LoopEdge(PATH path, EDGE edge)

int i, j;
EDGE loopEdge;

/* 最小的回路边 */
loopEdge.head = edge.tail;
loopEdge.tail = edge.head;

/* 寻找回路边的头端点,即包含新边的路径的尾端点 */
for (i = 0; i < path.edgesNumber; i++)
for (j = 0; j < path.edgesNumber; j++)
if (loopEdge.head == path.edge[j].head)
/* 扩大回路边 */
loopEdge.head = path.edge[j].tail;
break;



/* 寻找回路边的尾端点,即包含新边的路径的头端点 */
for (i = 0; i < path.edgesNumber; i++)
for (j = 0; j < path.edgesNumber; j++)
if (loopEdge.tail == path.edge[j].tail)
/* 扩大回路边 */
loopEdge.tail = path.edge[j].head;
break;




return (loopEdge);


/* 将新边加入到路径中 */
PATH AddEdge(EDGE edge, PATH path)

path.edge[path.edgesNumber++] = edge;
return path;


/* 计算花费矩阵当前阶数 */
int MatrixSize(MATRIX c, PATH path)

return (c.citiesNumber - path.edgesNumber);


/* 显示路径 */
void ShowPath(PATH path, MATRIX c)

int i, dist;
EDGE edge;
int n = path.edgesNumber;

dist = 0;
printf("\nThe path is: ");
for (i = 0; i < n; i++)
edge = path.edge[i];
printf("(%d, %d) ", edge.head + 1, edge.tail + 1);
dist += c.distance[edge.head][edge.tail];

/* printf("[Total Cost: %d]\n", dist); */


/* 显示花费矩阵 */
void ShowMatrix(MATRIX c)

int row, col;
int n = c.citiesNumber;

for (row = 0; row < n; row++)
for (col = 0; col < n; col++)
if (c.distance[row][col] != INFINITY)
printf("%3d", c.distance[row][col]);

else
printf(" -");


putchar('\n');

getch();
参考技术A 由于程序太长,直接传给你了。下面是主程序。
void main()

dijkstra s;
s.read();
s.algorithm();
s.output();

参考资料:http://ds4beginners.wordpress.com/2006/09/17/dijkstras-algorithm/

本回答被提问者采纳
参考技术B 直线不是最短的,虫洞才是最短的。

参考资料:你去网上炒炒

参考技术C 我不会但是我想要你的分看你给不给了。

Floyd-Warshall求图中任意两点的最短路径

原创


  除了DFS和BFS求图中最短路径的方法,算法Floyd-Warshall也可以求图中任意两点的最短路径。

  从图中任取两点A、B,A到B的最短路径无非只有两种情况:

  1:A直接到B这条路径即是最短路径(前提是存在此路径);

  2:A先通过其他点,再由其他点到B。

  我们并不知道A是否需要通过其他点间接到达B,所以只能比较,用A到B的直接路径和A先通过其他点

再间接到达B的路径长度进行比较,然后更新为较小值。

技术分享图片

  上图中若要求顶点4到顶点3的最短路径,可以比较顶点4直接到3的路径和顶点4先到1,再到3的路径。

更新为最小值,此时邻接矩阵matrix[4][3]存储的即为借用了顶点1后4到3的最短路径;然后再借用了1的

基础上再借用顶点2,此时再次比较matrix[4][3]和matrix[4][2]+matrix[2][3],更新为最小值;比较完

毕后matrix[4][3]乃存储了最短路径,求其他任意两点也是如此。

  总结一下,求图中任意两点的最短路径,通过比较一次取一个其他顶点间接到达的最短路径和直接路径

进行比较,更新为最小值即可。

import java.util.*;

public class Floyd_Warshall {
    
    static int v;    //顶点
    static int e;    //
    static int matrix[][];
    
    public static void main(String args[]) {
        Scanner reader=new Scanner(System.in);
        v=reader.nextInt();
        e=reader.nextInt();
        matrix=new int[v+1][v+1];    //编号从1开始
        //矩阵初始化
        for(int i=1;i<=v;i++) {
            for(int j=1;j<=v;j++) {
                if(i==j) {    //顶点本身
                    matrix[i][j]=0;
                }
                else {    //无穷
                    matrix[i][j]=99999;
                }
            }
        }
        //读入边
        for(int i=1;i<=e;i++) {
            int first_City=reader.nextInt();
            int second_City=reader.nextInt();
            int value=reader.nextInt();
            matrix[first_City][second_City]=value;    //有向图
        }
        for(int k=1;k<=v;k++) {    //只允许经过顶点k
            for(int i=1;i<=v;i++) {
                for(int j=1;j<=v;j++) {
                    if(matrix[i][k]+matrix[k][j]<matrix[i][j]) {
                        matrix[i][j]=matrix[i][k]+matrix[k][j];
                    }
                }
            }
        }
        for(int i=1;i<=v;i++) {
            for(int j=1;j<=v;j++) {
                System.out.print(matrix[i][j]+" ");
            }
            System.out.println();
        }
    }
}

测试用例:

输入:

4 8

1 2 2

2 3 3

3 4 1

4 3 12

1 3 6

3 1 7

1 4 4

4 1 5

输出:

0 2 5 4 

9 0 3 4 

6 8 0 1 

5 7 10 0 

12:30:24

2018-07-28



以上是关于求c++ 程序 网络上两点间的最短路径的主要内容,如果未能解决你的问题,请参考以下文章

a*算法求最短路径和floyd还有dijsktra算法求最短路径的区别?

Floyd(动态规划)求解任意两点间的最短路径(图解)

求图中任意两点之间最短路径有啥算法?

Floyd-Warshall求图中任意两点的最短路径

求java实现矩阵图上任意两点的最短路径源码

[Python] 弗洛伊德(Floyd)算法求图的直径并记录路径