预备知识-图的存储(邻接矩阵)
如果是无向图,需要注意什么?
此时最左下角也为100。即 5->0 也为100。
关于最短路径问题
求最短路径的基本思想
按照最短路径的长度递增的次序,依次求得——源点到其余各点的最短路径。
假设,从源点到顶点V1的最短路径是所有最短路径中长度最短者。
路径长度最短的最短路径的特点:
在这条路径上,必定只含一条弧,并且这条弧的权值最小。
路径长度次短的最短路径的特点:
它只可能有两种情况:
或者是直接从源点到该点(只含一条弧);
或者是从源点经过顶点v1,再到达该顶点(由两条弧组成)。
路径长度第三短的路径特点:
它可能有三种情况:
1、直接从源点到该点(只含一条弧);
2、从源点经过顶点v1,再到达该顶点(由两条弧组成);
3、从源点经过顶点v2,再到达该顶点。
其中:1、2在上一步已经做过比较,所以——每次只需要比较2个值!
其余最短路径的特点:
或者是:直接从源点到该点(只含一条弧);或者是:从源点经过已求得最短路径的顶点,再到达该顶点。
迪杰斯特拉算法
状态转移方程:
理论表示:Dist[k]=min(Map[i][k]+Dist[i])
其中,i为已经求出最短路的节点编号。
假设u为刚刚求得的最短路节点,则:
实际编程:Dis[k]=min(Dist[k],Map[u][k]+Dist[u])
下面我们来看一个例题:畅通工程续
某省自从实行了很多年的畅通工程计划后,终于修建了很多路。但是,每次从一个城镇到另一个城镇,常常有多种方案可以选择,这让行人很困扰。现在,请计算从起点到终点的最短距离。
每组输入数据第一行包含两个正整数N和M,分别代表城镇数目和已修建的道路数目。接下来M行每一行有三个整数A,B,X,表示城镇A和B有长为X的双向道路。再接下一行有两个整数S,T(0<=S,T<N),分别代表起点和终点。
Sample Input
3 3
0 1 1
0 2 3
1 2 1
0 2
3 1
0 1 1
1 2
Sample Output
2
-1
解题代码:
#include<bits/stdc++.h>
#define inf 0x7FFFFFFF
#define M 201
using namespace std;
int Map[M][M],Dist[M],visit[M];
int main()
{
int n,m,i,j,a,b,dis,start,Min,next,targe;
while(scanf("%d%d",&n,&m)==2)
{
for(i=0;i<n;i++)
{
visit[i]=1;
Dist[i]=inf;
for(j=0;j<n;j++)
Map[i][j]=inf;
}
while(m--)
{
scanf("%d%d%d",&a,&b,&dis);
Map[a][b]=min(Map[a][b],dis);
Map[b][a]=Map[a][b];
}
scanf("%d%d",&start,&targe);
Dist[start]=0;
visit[start]=0;
while(start!=targe)
{
Min=inf;
for(i=0;i<n;i++)
{
if(Map[start][i]!=inf)
Dist[i]=min(Dist[i],Map[start][i]+Dist[start]);
if(visit[i] && Dist[i] < Min)
{
next=i;
Min=Dist[i];
}
}
if(Min==inf)
break;
start=next;
visit[start]=0;
}
if(Dist[targe]==inf)
puts("-1");
else
printf("%d\n",Dist[targe]);
}
return 0;
}
运行结果: