【PAT甲级】1030 Travel Plan (30分)

解题过程的小记录,如有错误欢迎指出。

难度:三星(Dijkstra+DFS模板题,题不难,奈何我手生orz)

题目分析

给出各城市之间的距离和路过需要的花费,找出给定的起始点和终点的花费最少的最短路径,要求输出路径所经过的城市、最短距离和花费

注意点

  1. 采用邻接矩阵保存数据的话,距离和花费都要双重赋值,即G[u][v]=G[v][u]

我的解题过程

思路

  1. 先通过Dijkstra函数找出给定起点的单源最短路径,并在函数中用变长数组保存前驱们
  2. 再通过DFS函数走过每一条最短路径,遍历到叶子结点(起点)的时候根据第二加权项(花费),找出花费最少的路径记录在path中

bug

  1. Dijkstra中找未遍历过的距离最近的结点板块写错了,漏了更新MIN值
  2. DFS中没有把当前的结点push进tempPath中

代码

#include<iostream>
#include<vector>

using namespace std;

const int MAXV = 505;
const int INF = 1000000000;
int n, m, s, d;
int G[MAXV][MAXV], cost[MAXV][MAXV];
int dis[MAXV];
bool vis[MAXV] = { false };
vector<int> pre[MAXV], tempPath, path;
int mincost = INF;

void Dijkstra(int s) {
	fill(dis, dis + MAXV, INF);
	dis[s] = 0;
	for (int i = 0; i < n; i++) {
		int u = -1;
		int MIN = INF;
		for (int j = 0; j < n; j++) {
			if (vis[j] == false && dis[j] < MIN) {
				u = j;
				MIN = dis[j];//***写错的地方,原来漏写了,MIN不赋值就找不到最小值
			}
		}
		if (u == -1) return;
		vis[u] = true;
		for (int v = 0; v < n; v++) {
			if (vis[v] == false && G[u][v] != INF) {
				if (dis[v] > dis[u] + G[u][v]) {
					dis[v] = dis[u] + G[u][v];
					pre[v].clear();
					pre[v].push_back(u);
				}
				else if (dis[v] == dis[u] + G[u][v]) {
					pre[v].push_back(u);
				}
			}
		}
	}
}

void DFS(int end) {
	if (end == s) {
		tempPath.push_back(s);
		int totalcost = 0;
		for (int i = tempPath.size() - 1; i > 0; i--) {
			int u = tempPath[i], v = tempPath[i - 1];
			totalcost += cost[u][v];
		}
		if (totalcost < mincost) {
			mincost = totalcost;
			path = tempPath;
		}
		tempPath.pop_back();
		return;
	}
	tempPath.push_back(end);//****写错的地方,原来写在循环里面,新增的是前驱然而本节点都没有加入到里面去
	for (int i = 0; i < pre[end].size(); i++) {
		DFS(pre[end][i]);
	}
	tempPath.pop_back();
}

int main()
{
	scanf("%d %d %d %d", &n, &m, &s, &d);
	fill(G[0], G[0] + MAXV*MAXV, INF);
	for (int i = 0; i < m; i++) {
		int u, v, len, c;
		scanf("%d %d %d %d", &u, &v, &len, &c);
		G[u][v] = len;
		G[v][u] = len;
		cost[u][v] = c;
		cost[v][u] = c;
	}
	Dijkstra(s);
	DFS(d);
	for (int i = path.size() - 1; i >= 0; i--) {
		printf("%d ", path[i]);
	}
	printf("%d %d", dis[d], mincost);
    return 0;
}

dalao的代码

全部代码因版权原因不放出来,大家可以自行去柳神博客购买或者参考晴神的上机笔记~

借鉴点

本题还可以只用Dijkstra一个函数完成(在更新那里对第二权重大做文章,完整代码在晴神的算法笔记上有),个人感觉对于不需要输出路径的采用一个函数完成比较方便,对于要输出路径的或者第二权重复杂的采用Dijkstra+DFS的模板更加方便

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值