数据结构(四)图 —— 编程作业 06 :旅游规划

数据结构系列内容的学习目录 → \rightarrow 浙大版数据结构学习系列内容汇总

  题目描述: 有了一张自驾旅游路线图,就会知道城市间的高速公路长度、以及该公路要收取的过路费。现在需要写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径。如果有若干条路径都是最短的,那么需要输出最便宜的一条路径。

  输入格式: 输入数据的第1行给出4个正整数N、M、S、D,其中N(2≤N≤500)是城市的个数,顺便假设城市的编号为0~(N−1);M是高速公路的条数;S是出发地的城市编号;D是目的地的城市编号。
        随后的M行中,每行给出一条高速公路的信息,分别是:城市1、城市2、高速公路长度、收费额,中间用空格分开,数字均为整数且不超过500。
        输入保证解的存在。

  输出格式: 在一行里输出路径的长度和收费总额,数字间以空格分隔,输出结尾不能有多余空格。

  输入样例:

4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20

  输出样例:

3 40

  解题思路: ■ 城市为结点
        ■ 公路为边
         ⋄ 权重1:距离
         ⋄ 权重2:收费
        ■ 单源最短路
         ⋄ Dijkstra 一 距离
         ⋄ 等距离时按收费更新

在这里插入图片描述
  Dijkstra算法的其他类似问题:
   ■ 要求数最短路径有多少条
     ⋄ count[s] = 1;
     ⋄ 如果找到更短路:count[W]=count[V];
     ⋄ 如果找到等长路:count[W]+=count[V];
   ■ 要求边数最少的最短路
     ⋄ count[s] = 0 ;
     ⋄ 如果找到更短路: count[w]=count[V]+1;
     ⋄ 如果找到等长路: count[w]=count[V]+1;

  代码实现:

#include<iostream>
using namespace std;
#define INF 1000000
#define MaxVertex 505

typedef int Vertex;
int value[MaxVertex][MaxVertex];    //收费矩阵
int G[MaxVertex][MaxVertex];    //距离矩阵
int dist[MaxVertex];  // 距离
int cost[MaxVertex];  // 费用
bool collected[MaxVertex];  // 被收录集合

int N;   // 城市的个数
int M;   // 高速公路的条数
int S;  // 出发地的城市编号
int D;  // 目的地的城市编号

// 初始化图信息
void BuildGraph() 
{
	Vertex v1, v2, w1, w2;
	cin >> N >> M >> S >> D;  // 输入:城市的个数、高速公路的条数、出发地的城市编号、目的地的城市编号
	for (Vertex i = 0; i < N; i++) 
	{
		for (Vertex j = 0; j < N; j++) 
		{
			G[i][j] = INF;
			value[i][j] = INF;
		}
		cost[i] = 0;
		collected[i] = false;
		dist[i] = INF;
	}
	for (int i = 0; i < M; i++) 
	{
		cin >> v1 >> v2 >> w1 >> w2;  // 输入:城市1、城市2、高速公路长度、收费额
		G[v1][v2] = w1;
		G[v2][v1] = w1;
		value[v1][v2] = w2;
		value[v2][v1] = w2;
	}
}

void Init() 
{
	dist[S] = 0;
	collected[S] = true;
	for (Vertex i = 0; i < N; i++)
		if (G[S][i]) 
		{
			dist[i] = G[S][i];
			cost[i] = value[S][i];
		}
}

// 查找未收录顶点中dist最小者
Vertex FindMin() 
{
	int min = INF;
	Vertex x = -1;
	for (Vertex i = 0; i < N; i++)
		if (S != i && !collected[i] && dist[i] < min) 
		{
			min = dist[i];
			x = i;
		}
	return x;
}


void Dijkstra() 
{
	Init();
	while (1) 
	{
		Vertex v = FindMin();
		if (v == -1)
			break;
		collected[v] = true;
		for (Vertex w = 0; w < N; w++) 
		{
			if (!collected[w] && G[v][w]) 
			{
				if (dist[v] + G[v][w] < dist[w]) 
				{
					dist[w] = dist[v] + G[v][w];
					cost[w] = cost[v] + value[v][w];
				}
				else if (dist[v] + G[v][w] == dist[w] && cost[v] + value[v][w] < cost[w]) 
				{
					cost[w] = cost[v] + value[v][w];
				}
			}
		}
	}
}

int main() 
{
	BuildGraph();
	Dijkstra();
	cout << dist[D] << " " << cost[D] << endl;
	system("pause");
	return 0;
}

  测试: 输入样例的测试效果如下图所示。

在这里插入图片描述

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值