最短路径

Dijkstra算法实现最短路径

问题描述

若用有向网表示某地区的公路交通网,其中顶点表示该地区的一些主要场所,弧表示已有的公交线路,弧上的权表示票价。试设计一个交通咨询系统,指导乘客以最少花费从该地区中的某一场所到达另一场所。
基本要求
(1) 从文件中读入有向网中顶点的数量和顶点间的票价的矩阵。
(2) 以用户指定的起点和终点,输出从起点到终点的花费。
测试数据
输入
(文件)
5
-1 10 3 20 -1
-1 -1 -1 5 -1
-1 2 -1 -1 15
-1 -1 -1 -1 11
-1 -1 -1 -1 -1
(用户)
起点0
终点4

输出
18
实现提示
(1) 设图的顶点大于1个,不超过30个,每个顶点用一个编号表示(如果一个图有n个顶点,则它们的编号分别为0, 1, 2, 3, …, n-1)。
(2) 此题为求有向网中顶点间最短路径问题,可建立以票价为权的邻接矩阵,用Dijkstra算法求最短路径长度。
(3) Dijkstra算法中有一个辅助向量D,表示当前所找到的从源点到其它点的最短路径长度。因为每次都要在D中找最小值,为提高性能,用最小值堆的优先队列存储D值。
(4) 考虑没有路径时的输出。
选作内容
(1) 以用户指定的起点,输出到其它各点的花费。
(2) 以用户指定的起点和终点,输出从起点到终点的花费以及路径(经过的中间顶点)。

 必做

  1 #include<iostream>
  2 #include<fstream>
  3 #include<stdio.h>
  4 #include<stdlib.h>
  5 #include<string.h>
  6 #include<string>
  7 #define maxSize 100
  8 #define maxint 1000
  9 typedef enum{ FALSE, TRUE }Boolean;
 10 Boolean visited[maxSize];
 11 using namespace std;
 12 int read(int graph[][maxSize])
 13 {
 14     FILE *in;
 15     in=fopen("path","r");
 16     int n,i,j,num;
 17     fscanf(in,"%d",&n);
 18 
 19     for(i=0;i<n;i++)
 20     {
 21         for(j=0;j<n;j++)
 22         {
 23             fscanf(in,"%d",&num);
 24             if(num==-1)
 25                 num=maxint;
 26             graph[i][j]=num;
 27         }
 28     }
 29 
 30 
 31     fclose(in);
 32     return n;
 33 }
 34 int first(int v,int n,int graph[maxSize][maxSize])
 35 {
 36     int j;
 37     int ret;
 38     for(j=1;j<n;j++)
 39     {
 40         if(graph[v][j]!=-1)
 41             {return j;break;}
 42     }
 43     if(j==n)
 44         return n;
 45 }
 46 int next(int v,int w,int n,int graph[maxSize][maxSize])
 47 {
 48     int j;
 49     for(j=w+1;j<n;j++)
 50     {
 51         if(graph[v][j]!=-1)
 52             {return j;break;}
 53     }
 54     if(j==n)
 55     return n;
 56 }
 57 int minn(int *dist,int n,int v)
 58 {
 59     int j,mi;
 60 
 61     for(j=0;j<n;j++)
 62     {
 63         if(dist[j]!=maxint&&visited[j]==FALSE)
 64             {mi=j;break;}
 65     }
 66     if(j==n)
 67     {cout<<"不存在路径"<<endl;return -1;}
 68     for(j++;j<n;j++)
 69     {
 70         if(dist[j]<dist[mi]&&dist[j]!=maxint&&visited[j]==FALSE)
 71             mi=j;
 72     }
 73     return mi;
 74 }
 75 bool Dijkstra(int n, int v, int *dist, int graph[maxSize][maxSize])
 76 {
 77     //找到与V相邻的最短路径的结点
 78     int i,j,mi,w;
 79     for(j=0;j<n;j++)
 80         visited[j]=FALSE;//初始化为都没有被访问
 81     for(j=0;j<n;j++)
 82         {dist[j]=graph[v][j];}
 83     mi=minn(dist,n,v);
 84 
 85     visited[mi]=TRUE;
 86     cout<<"mi___"<<mi<<endl;
 87     i=0;
 88     while(i<n-1)
 89     {
 90 
 91 
 92         for(j=0;j<n;j++)
 93         {
 94             if(dist[j]>dist[mi]+graph[mi][j])
 95             {dist[j]=dist[mi]+graph[mi][j];}
 96         }
 97         visited[mi]=TRUE;
 98         mi=minn(dist,n,mi);
 99         cout<<"mi  "<<mi<<endl;
100         i++;
101     }
102 }
103 int main()
104 {
105     int graph[maxSize][maxSize],n,i,j;
106     int from,to;
107     int dis[maxSize],pre[maxSize];
108     n=read(graph);
109 
110     for(i=0;i<n;i++)
111     {
112         for(j=0;j<n;j++)
113         {
114             cout<<graph[i][j]<<" ";
115         }
116         cout<<endl;
117     }
118     cout<<"起点 :";
119     cin>>from;
120     cout<<"终点 :";
121     cin>>to;
122 
123     Dijkstra(n,from,dis,graph);
124     for(i=0;i<n;i++)
125         cout<<dis[i]<<" "<<endl;
126     cout<< ""<<from<<""<<to<<"的最短距离:  "<<dis[to]<<endl;
127     return 0;
128 }
View Code

选做1

  1 #include<iostream>
  2 #include<fstream>
  3 #include<stdio.h>
  4 #include<stdlib.h>
  5 #include<string.h>
  6 #include<string>
  7 #define maxSize 100
  8 #define maxint 1000
  9 typedef enum{ FALSE, TRUE }Boolean;
 10 Boolean visited[maxSize];
 11 using namespace std;
 12 int read(int graph[][maxSize])
 13 {
 14     FILE *in;
 15     in=fopen("path","r");
 16     int n,i,j,num;
 17     fscanf(in,"%d",&n);
 18 
 19     for(i=0;i<n;i++)
 20     {
 21         for(j=0;j<n;j++)
 22         {
 23             fscanf(in,"%d",&num);
 24             if(num==-1)
 25                 num=maxint;
 26             graph[i][j]=num;
 27         }
 28     }
 29 
 30 
 31     fclose(in);
 32     return n;
 33 }
 34 int first(int v,int n,int graph[maxSize][maxSize])
 35 {
 36     int j;
 37     int ret;
 38     for(j=1;j<n;j++)
 39     {
 40         if(graph[v][j]!=-1)
 41             {return j;break;}
 42     }
 43     if(j==n)
 44         return n;
 45 }
 46 int next(int v,int w,int n,int graph[maxSize][maxSize])
 47 {
 48     int j;
 49     for(j=w+1;j<n;j++)
 50     {
 51         if(graph[v][j]!=-1)
 52             {return j;break;}
 53     }
 54     if(j==n)
 55     return n;
 56 }
 57 int minn(int *dist,int n,int v)
 58 {
 59     int j,mi;
 60 
 61     for(j=0;j<n;j++)
 62     {
 63         if(dist[j]!=maxint&&visited[j]==FALSE)
 64             {mi=j;break;}
 65     }
 66     if(j==n)
 67     {
 68         //cout<<"不存在路径"<<endl;
 69         return -1;
 70     }
 71     for(j++;j<n;j++)
 72     {
 73         if(dist[j]<dist[mi]&&dist[j]!=maxint&&visited[j]==FALSE)
 74             mi=j;
 75     }
 76     return mi;
 77 }
 78 bool Dijkstra(int n, int v, int *dist, int graph[maxSize][maxSize])
 79 {
 80     //找到与V相邻的最短路径的结点
 81     int i,j,mi,w;
 82     for(j=0;j<n;j++)
 83         visited[j]=FALSE;//初始化为都没有被访问
 84     for(j=0;j<n;j++)
 85         {dist[j]=graph[v][j];}
 86     mi=minn(dist,n,v);
 87 
 88     visited[mi]=TRUE;
 89     //cout<<"mi___"<<mi<<endl;
 90     i=0;
 91     while(i<n-1)
 92     {
 93 
 94 
 95         for(j=0;j<n;j++)
 96         {
 97             if(dist[j]>dist[mi]+graph[mi][j])
 98             {dist[j]=dist[mi]+graph[mi][j];}
 99         }
100         visited[mi]=TRUE;
101         mi=minn(dist,n,mi);
102       //  cout<<"mi  "<<mi<<endl;
103         i++;
104     }
105 }
106 int main()
107 {
108     int graph[maxSize][maxSize],n,i,j;
109     int from,to;
110     int dis[maxSize],pre[maxSize];
111     n=read(graph);
112 
113     for(i=0;i<n;i++)
114     {
115         for(j=0;j<n;j++)
116         {
117             cout<<graph[i][j]<<" ";
118         }
119         cout<<endl;
120     }
121     cout<<"起点 :";
122     cin>>from;
123     cout<<"终点 :";
124     cin>>to;
125 
126     Dijkstra(n,from,dis,graph);
127     for(i=0;i<n;i++)
128         cout<<"起点到点"<<i<<"的最短距离"<<dis[i]<<" "<<endl;
129     //cout<< "从"<<from+1<<"到"<<to+1<<"的最短距离:  "<<dis[to]<<endl;
130     return 0;
131 }
View Code

选做2

  1 /***************************************
  2 * About:    有向图的Dijkstra算法实现
  3 * Author:   Tanky Woo
  4 * Blog:     www.WuTianQi.com
  5 ***************************************/
  6 
  7 #include <iostream>
  8 #include<stdio.h>
  9 using namespace std;
 10 
 11 const int maxnum = 100;
 12 const int maxint = 1000;
 13 
 14 int read(int graph[][maxnum])
 15 {
 16     FILE *in;
 17     in=fopen("path","r");
 18     int n,i,j,num;
 19     fscanf(in,"%d",&n);
 20 
 21     for(i=1;i<=n;i++)
 22     {
 23         for(j=1;j<=n;j++)
 24         {
 25             fscanf(in,"%d",&num);
 26             if(num==-1)
 27                 num=maxint;
 28             graph[i][j]=num;
 29         }
 30     }
 31 
 32 
 33     fclose(in);
 34     return n;
 35 }
 36 
 37 void Dijkstra(int n, int v, int *dist, int *prev, int c[maxnum][maxnum])
 38 {
 39     bool s[maxnum];    // 判断是否已存入该点到S集合中
 40     for(int i=1; i<=n; ++i)
 41     {
 42         dist[i] = c[v][i];
 43         s[i] = 0;     // 初始都未用过该点
 44         if(dist[i] == maxint)
 45             prev[i] = 0;
 46         else
 47             prev[i] = v;
 48     }
 49     dist[v] = 0;
 50     s[v] = 1;
 51 
 52     // 依次将未放入S集合的结点中,取dist[]最小值的结点,放入结合S中
 53     // 一旦S包含了所有V中顶点,dist就记录了从源点到所有其他顶点之间的最短路径长度
 54     for(int i=2; i<=n; ++i)
 55     {
 56         int tmp = maxint;
 57         int u = v;
 58         // 找出当前未使用的点j的dist[j]最小值
 59         for(int j=1; j<=n; ++j)
 60             if((!s[j]) && dist[j]<tmp)
 61             {
 62                 u = j;              // u保存当前邻接点中距离最小的点的号码
 63                 tmp = dist[j];
 64             }
 65         s[u] = 1;    // 表示u点已存入S集合中
 66 
 67         // 更新dist
 68         for(int j=1; j<=n; ++j)
 69             if((!s[j]) && c[u][j]<maxint)
 70             {
 71                 int newdist = dist[u] + c[u][j];
 72                 if(newdist < dist[j])
 73                 {
 74                     dist[j] = newdist;
 75                     prev[j] = u;
 76                 }
 77             }
 78     }
 79 }
 80 
 81 void searchPath(int *prev,int v, int u)
 82 {
 83     int que[maxnum];
 84     int tot = 1;
 85     que[tot] = u;
 86     tot++;
 87     int tmp = prev[u];
 88     while(tmp != v)
 89     {
 90         que[tot] = tmp;
 91         tot++;
 92         tmp = prev[tmp];
 93     }
 94     que[tot] = v;
 95     for(int i=tot; i>=1; --i)
 96         if(i != 1)
 97             cout << que[i] << " -> ";
 98         else
 99             cout << que[i] << endl;
100 }
101 
102 int main()
103 {
104 
105     //freopen("input.txt", "r", stdin);
106     // 各数组都从下标1开始
107     int dist[maxnum];     // 表示当前点到源点的最短路径长度
108     int prev[maxnum];     // 记录当前点的前一个结点
109     int graph[maxnum][maxnum];   // 记录图的两点间路径长度
110     int n;
111     n=read(graph);
112 
113 
114     for(int i=1; i<=n; ++i)
115         dist[i] = maxint;
116     for(int i=1; i<=n; ++i)
117     {
118         for(int j=1; j<=n; ++j)
119             cout<<graph[i][j]<<" ";
120         cout<<endl;
121     }
122     int from,to;
123     cout<<"起点:";
124     cin>>from;
125     cout<<"终点:";
126     cin>>to;
127     Dijkstra(n, from+1, dist, prev, graph);
128 
129     // 最短路径长度
130     cout << "起点到终点的最短路径长度: " << dist[to+1] << endl;
131 
132     // 路径
133     cout << "起点到终点的路径为: ";
134     searchPath(prev, from+1, to+1);
135 }
View Code

文件名是path    二进制文件

posted @ 2016-05-18 17:45  天气晚来秋  阅读(360)  评论(0编辑  收藏  举报