07-图6 旅游规划 (25分)(7-9 旅游规划 (25分))

1 篇文章 0 订阅
1 篇文章 0 订阅

https://pintia.cn/problem-sets/15/problems/717

数据结构与算法题目集(中文)--> 编程题 --> 7-9

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

输入格式:

输入说明:输入数据的第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

算法思路:普通的单源最短路径算法(改造一下即可),只不过G[ i ][ j ] 不单单要存长度,还要存一个花费,所以采用邻接矩阵,不过里面存的是pair,first存距离,second存花费。 

#include<bits/stdc++.h>
using namespace std;
const int INF = INT_MAX-10;

//dijkstra
vector<int> dist;
vector<int> cost;
vector<bool> vis;
vector<vector<pair<int, int>>> G;
int n, m, s, d;
void dijkstra(int s)
{
	//初始化
	dist[s] = 0;
	cost[s] = 0;
	vis[s] = true;

	//开始dp
	int v = s;
	int w;
	while (v != d)
	{
		for (unsigned int i = 0; i < G[v].size(); i++)
		{
			w = i;
			int dis = G[v][i].first;
			int cos = G[v][i].second;
			if (dis==INF) continue;

			if (!vis[w])  //未被访问过
			{
				if (dist[v] + dis < dist[w])
				{
					dist[w] = dist[v] + dis;
					cost[w] = cost[v] + cos;
				}
				else if (dist[v] + dis == dist[w])
				{
					if (cost[v] + cos < cost[w])
						cost[w] = cost[v] + cos;
				}
			}
		}
		//更新v,未收录顶点中dist最小者,可以使用堆优化
		//本题一定存在解,所以没有判断这样的v不在的情况,如果不存在也就是v或者minDis没有更新,那么直接break即可
		int minDis = INF;
		for (int i = 0; i < n; i++)
		{
			if (dist[i] < minDis && !vis[i])   //注:!vis[i] 
			{
				minDis = dist[i];
				v = i;	//更新 v 
			}
		}
		vis[v] = true;	//以新的v为起点。将其标记为true 
	}//while
}



int main() {
	cin >> n >> m >> s >> d;

	dist = vector<int>(n,INF);
	cost = vector<int>(n, INF);
	vis = vector<bool>(n, false);
	G = vector<vector<pair<int, int>>>(n, vector<pair<int, int>>(n, {INF,INF}));

	int x, y, len, val;
	for (int i = 0; i < m;i++) {
		cin >> x >> y >> len >> val;
		G[x][y].first = len;
		G[x][y].second = val;
		G[y][x].first = len;
		G[y][x].second = val;
	}

	dijkstra(s);
	cout << dist[d] << " " << cost[d] << endl;
	system("pause");
	return 0;
}
//推荐这个版本写法
#include<bits/stdc++.h>
using namespace std;
const int INF = INT_MAX - 10;

void dijkstra(vector<vector<pair<int, int>>>& g, vector<int>& dist, vector<int>& cost, int s, int d) {
	int n = g.size();
	vector<bool> collected(n, false);
	int v, w;
	//初始化
	for (v = 0; v < n; v++) {
		dist[v] = g[s][v].first;
		cost[v] = g[s][v].second;
	}
	//收录s
	collected[s] = true;
	dist[s] = 0;
	cost[s] = 0;
	v = s;

	while (v!=d) {
		//v=未收录顶点中dist最小者
		int tmp = INF;
		for (int i = 0; i < n; i++) {
			if (!collected[i]) {
				if (dist[i] < tmp) {
					tmp = dist[i];
					v = i;
				}
			}
		}
		collected[v] = true;
		//对图中每个点w进行操作
		for (w = 0; w < n; w++) {
			if (!collected[w] && g[v][w].first != INF) {
				if (dist[v] + g[v][w].first < dist[w]) {
					dist[w] = dist[v] + g[v][w].first;
					cost[w] = cost[v] + g[v][w].second;
				}
				else if (dist[v] + g[v][w].first == dist[w]) {
					if (cost[v] + g[v][w].second < cost[w]) {
						cost[w] = cost[v] + g[v][w].second;
					}
				}
			}
		}
		
	}
}

int main() {
	int N, M, S, D;
	cin >> N >> M >> S >> D;

	vector<vector<pair<int, int>>> g(N, vector<pair<int, int>>(N, {INF,INF}));
	int v, w, l, c;
	for (int i = 0; i < M; i++) {
		cin >> v >> w >> l >> c;
		g[v][w].first = l;
		g[v][w].second = c;
		g[w][v].first = l;
		g[w][v].second = c;
	}

	vector<int> dist(N, INF);
	vector<int> cost(N, INF);
	dijkstra(g, dist, cost, S, D);
	cout << dist[D] << " " << cost[D] << endl;

	system("pause");
	return 0;

}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值