1030. Travel Plan (30)

本文介绍了一道PAT-A级编程题的解答过程,题目要求求解单源最短路径及最低成本路径。通过使用Dijkstra算法实现,并附带了完整的C++代码实现细节。

1. 原题: https://www.patest.cn/contests/pat-a-practise/1030

2. 思路:

题意:单源最短路径,路径相等则判断费用最小。比较简单。
思路:直接用dijkstra算法,同时把到达某点的上一个
结点存储在path里,用于输出路径。

3. 源码(已AC):

#include<iostream>
using namespace std;

const int MAX = 500;	//最大结点数
const int INF = 0x7FFFFFF;	//无穷大
int G[MAX][MAX];	//存储路径长度
int cost[MAX][MAX];	//存储费用
int path[MAX];	//存储上一个结点
int dist[MAX];	//存储源点到某点的距离
int min_cost[MAX];	//存储费用
int collect[MAX] = {0};	//表示某点已收录到最短路径中
int N, M, S, D;

void dijkstra();	//dijkstra函数
int Find_min();	//找到未收录的最小路径
void print(int d);	//递归输出函数

int main()
{
	//freopen("in.txt", "r", stdin);
	cin >> N >> M >> S >> D;
	for (int i = 0; i < N; i++)	//初始化
	{
		path[i] = -1;
		for (int j = 0; j < N; j++)
		{
			G[i][j] = INF;
			cost[i][j] = INF;
		}
		dist[i] = INF;
		min_cost[i] = INF;
	}

	for (int i = 0; i < M; i++)//读入数据
	{
		int c1, c2, len, expen;
		cin >> c1 >> c2 >> len >> expen;
		G[c1][c2] = G[c2][c1] = len;
		cost[c1][c2] = cost[c2][c1] = expen;
	}
	dijkstra();

	return 0;
}

void dijkstra()//dijkstra函数
{
	dist[S] = 0;
	min_cost[S] = 0;

	while(1)	//循环处理
	{
		int v = Find_min();
		if (v == -1)		//-1表示已全部查找完,跳出
			break;
		collect[v] = 1;

		for (int w = 0; w < N; w++)	//收录v后更新未收录的结点的状态
		{
			if(collect[w] == 0 && G[v][w] < INF)
			{
				if(dist[v] + G[v][w] < dist[w])
				{
					dist[w] = dist[v] + G[v][w];
					path[w] = v;
					min_cost[w] = min_cost[v] + cost[v][w];
				}
				else if (dist[v] + G[v][w] == dist[w])
				{
					if (min_cost[v] + cost[v][w] < min_cost[w])
					{
						min_cost[w] = min_cost[v] + cost[v][w];
						path[w] = v;
					}
				}
			}
		}
	}

	print(D);
	printf("%d %d\n", dist[D], min_cost[D]);

	return;
}

int Find_min()//找到未收录的最小路径
{
	int min_dist = INF;
	int min_id = -1;
	for (int i = 0; i < N; i++)
	{
		if(collect[i] == 0 && dist[i] < min_dist)
		{
			min_dist = dist[i];
			min_id = i;
		}
	}

	return min_id;
}

void print(int d)//递归输出函数
{
	if (path[d] == -1)
	{
		printf("%d ", d);
		return;
	}
	print(path[d]);
	printf("%d ", d);

	return;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值