最短路径问题

预备知识-图的存储(邻接矩阵)

如果是无向图,需要注意什么?

此时最左下角也为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;
}

运行结果:

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值