1111 Online Map (30分)

12 篇文章 0 订阅
6 篇文章 0 订阅

在这里插入图片描述
在这里插入图片描述
可以直接Dijkstra,也可以先用Dijkstra求出所有最短路,再用DFS选出最佳的一条。
直接用Dijkstra解决,需要设置额外的数组:

#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
int intersectNum, streetNum;
int source, destination;
const int inf = 0x7fffffff;
struct node {
	int time, length;
	node() {
		time = inf;
		length = inf;
	}
}map[520][520];
bool visited[520] = { false };
int minimumDistance[520];
int minimumTime[520];
int previous[520];	//各结点的前驱结点
int intersection[520] = { 0 };
vector<int> getPath(int cur) {
	vector<int> path;
	while (cur != -1) {
		path.push_back(cur);
		cur = previous[cur];
	}
	return path;
}
int main() {
	scanf("%d %d", &intersectNum, &streetNum);
	for (int i = 0;i < streetNum;i++) {
		int v1, v2, oneway, length, time;
		scanf("%d %d %d %d %d", &v1, &v2, &oneway, &length, &time);
		map[v1][v2].length = length;
		map[v1][v2].time = time;
		if (oneway == 0) {
			map[v2][v1].length = length;
			map[v2][v1].time = time;
		}
	}
	scanf("%d %d", &source, &destination);

	//Dijkstra找距离最短路
	fill(minimumDistance, minimumDistance + 520, inf);
	fill(minimumTime, minimumTime + 520, inf);
	fill(visited, visited + 520, false);
	fill(previous, previous + 520, -1);
	minimumDistance[source] = 0;
	minimumTime[source] = 0;
	for (int i = 0;i < intersectNum;i++) {
		int u = -1, minDis = inf;
		for (int j = 0;j < intersectNum;j++) {
			if (!visited[j] && minimumDistance[j] < minDis) {
				u = j;
				minDis = minimumDistance[j];
			}
		}
		if (u == -1)
			break;
		visited[u] = true;
		for (int v = 0;v < intersectNum;v++) {
			if (!visited[v] && map[u][v].length != inf) {
				if (map[u][v].length + minimumDistance[u] < minimumDistance[v] ||
					map[u][v].length + minimumDistance[u] == minimumDistance[v] && map[u][v].time + minimumTime[u] < minimumTime[v]) {
					previous[v] = u;
					minimumDistance[v] = map[u][v].length + minimumDistance[u];
					minimumTime[v] = map[u][v].time + minimumTime[u];
				}
			}
		}
	}
	vector<int> shortestDisPath = getPath(destination);
	int minDistance = minimumDistance[destination];

	//Dijkstra找时间最短路
	fill(minimumDistance, minimumDistance + 520, inf);
	fill(minimumTime, minimumTime + 520, inf);
	fill(visited, visited + 520, false);
	fill(previous, previous + 520, -1);
	fill(intersection, intersection + 520, inf);
	minimumTime[source] = 0;
	minimumDistance[source] = 0;
	intersection[source] = 0;
	for (int i = 0;i < intersectNum;i++) {
		int u = -1, minT = inf;
		for (int j = 0;j < intersectNum;j++) {
			if (!visited[j] && minimumTime[j] < minT) {
				u = j;
				minT = minimumTime[j];
			}
		}
		if (u == -1)
			break;
		visited[u] = true;
		for (int v = 0;v < intersectNum;v++) {
			if (!visited[v] && map[u][v].time != inf) {
				if (map[u][v].time + minimumTime[u] < minimumTime[v] ||
					map[u][v].time + minimumTime[u] == minimumTime[v] && intersection[u] + 1 < intersection[v]) {
					previous[v] = u;
					minimumTime[v] = map[u][v].time + minimumTime[u];
					intersection[v] = intersection[u] + 1;
				}
			}
		}
	}
	vector<int> shortestTimePath = getPath(destination);
	int minTime = minimumTime[destination];
	if (shortestTimePath == shortestDisPath) {
		printf("Distance = %d; Time = %d: ", minDistance, minTime);
		for (int i = shortestTimePath.size() - 1;i >= 0;i--) {
			printf("%d", shortestTimePath[i]);
			if (i != 0)
				printf(" -> ");
		}
	}
	else {
		printf("Distance = %d: ", minDistance);
		for (int i = shortestDisPath.size() - 1;i >= 0;i--) {
			printf("%d", shortestDisPath[i]);
			if (i != 0)
				printf(" -> ");
		}
		printf("\n");
		printf("Time = %d: ", minTime);
		for (int i = shortestTimePath.size() - 1;i >= 0;i--) {
			printf("%d", shortestTimePath[i]);
			if (i != 0)
				printf(" -> ");
		}
	}
}

先求出所有最短路,再从中找出最佳路径,需要配合dfs求解:

#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;

int intersectNum, streetNum;
int source, destination;
const int inf = 0x7fffffff;
struct node {
	int time, length;
	node() {
		time = inf;
		length = inf;
	}
}map[520][520];
bool visited[520] = { false };
int minimumDistance[520];
int minimumTime[520];
vector<int> previous[520];	//各结点的前驱结点

int minTime = inf;
vector<int> shortestDisPath;
void findMinDisPath(int cur, int curTime, vector<int> path) {
	if (cur == source) {
		if (curTime < minTime) {
			shortestDisPath = path;
			minTime = curTime;
		}
		return;
	}
	for (int i = 0;i < previous[cur].size();i++) {
		path.push_back(previous[cur][i]);
		findMinDisPath(previous[cur][i], curTime + map[previous[cur][i]][cur].time, path);
		path.pop_back();
	}
}

int minIntersection = inf;
vector<int> shortestTimePath;
void findMinTimePath(int cur, vector<int> path) {
	if (cur == source) {
		if (path.size() < minIntersection) {
			shortestTimePath = path;
			minIntersection = path.size();
		}
		return;
	}
	for (int i = 0;i < previous[cur].size();i++) {
		path.push_back(previous[cur][i]);
		findMinTimePath(previous[cur][i], path);
		path.pop_back();
	}
}

int main() {
	scanf("%d %d", &intersectNum, &streetNum);
	for (int i = 0;i < streetNum;i++) {
		int v1, v2, oneway, length, time;
		scanf("%d %d %d %d %d", &v1, &v2, &oneway, &length, &time);
		map[v1][v2].length = length;
		map[v1][v2].time = time;
		if (oneway == 0) {
			map[v2][v1].length = length;
			map[v2][v1].time = time;
		}
	}
	scanf("%d %d", &source, &destination);

	//Dijkstra找距离最短路
	fill(minimumDistance, minimumDistance + 520, inf);
	fill(visited, visited + 520, false);
	minimumDistance[source] = 0;
	for (int i = 0;i < intersectNum;i++) {
		int u = -1, minDis = inf;
		for (int j = 0;j < intersectNum;j++) {
			if (!visited[j] && minimumDistance[j] < minDis) {
				u = j;
				minDis = minimumDistance[j];
			}
		}
		if (u == -1)
			break;
		visited[u] = true;
		for (int v = 0;v < intersectNum;v++) {
			if (!visited[v] && map[u][v].length != inf) {
				if (map[u][v].length + minimumDistance[u] < minimumDistance[v]) {
					previous[v].clear();
					previous[v].push_back(u);
					minimumDistance[v] = map[u][v].length + minimumDistance[u];
				}
				else if (map[u][v].length + minimumDistance[u] == minimumDistance[v]) {
					previous[v].push_back(u);
				}
			}
		}
	}
	vector<int> temp;
	temp.push_back(destination);
	findMinDisPath(destination, 0, temp);

	//Dijkstra找时间最短路
	fill(minimumTime, minimumTime + 520, inf);
	fill(visited, visited + 520, false);
	for (int i = 0;i < 520;i++)
		previous[i].clear();
	minimumTime[source] = 0;
	for (int i = 0;i < intersectNum;i++) {
		int u = -1, minT = inf;
		for (int j = 0;j < intersectNum;j++) {
			if (!visited[j] && minimumTime[j] < minT) {
				u = j;
				minT = minimumTime[j];
			}
		}
		if (u == -1)
			break;
		visited[u] = true;
		for (int v = 0;v < intersectNum;v++) {
			if (!visited[v] && map[u][v].time != inf) {
				if (map[u][v].time + minimumTime[u] < minimumTime[v]) {
					previous[v].clear();
					previous[v].push_back(u);
					minimumTime[v] = map[u][v].time + minimumTime[u];
				}
				if (map[u][v].time + minimumTime[u] == minimumTime[v]) {
					previous[v].push_back(u);
				}
			}
		}
	}

	temp.clear();
	temp.push_back(destination);
	findMinTimePath(destination, temp);

	bool samePath = true;
	if (shortestDisPath.size() != shortestTimePath.size()) {
		samePath = false;
	}
	else {
		for (int i = 0;i < shortestDisPath.size();i++) {
			if (shortestDisPath[i] != shortestTimePath[i])
				samePath = false;
			break;
		}
	}
	if (shortestTimePath == shortestDisPath) {
		printf("Distance = %d; Time = %d: ", minimumDistance[destination], minimumTime[destination]);
		for (int i = shortestTimePath.size() - 1;i >= 0;i--) {
			printf("%d", shortestTimePath[i]);
			if (i != 0)
				printf(" -> ");
		}
	}
	else {
		printf("Distance = %d: ", minimumDistance[destination]);
		for (int i = shortestDisPath.size() - 1;i >= 0;i--) {
			printf("%d", shortestDisPath[i]);
			if (i != 0)
				printf(" -> ");
		}
		printf("\n");
		printf("Time = %d: ", minimumTime[destination]);
		for (int i = shortestTimePath.size() - 1;i >= 0;i--) {
			printf("%d", shortestTimePath[i]);
			if (i != 0)
				printf(" -> ");
		}
	}
}

二刷:
改用cin后比一刷代码的运行时间更长。

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int inf = 0x7fffffff;
int vertexNum, edgeNum, source, dest;
struct node {
	int length = inf, time = inf;
}map[500][500];
bool visited[500];
int totalLength[500];
int totalTime[500];
int totalVertex[500];
int shortestPreNode[500];
int fastestPreNode[500];
int main() {
	cin >> vertexNum >> edgeNum;
	for (int i = 0; i < edgeNum; i++) {
		int v1, v2, oneway, len, time;
		cin >> v1 >> v2 >> oneway >> len >> time;
		map[v1][v2].length = len;
		map[v1][v2].time = time;
		if (oneway == 0) {
			map[v2][v1].length = len;
			map[v2][v1].time = time;
		}
	}
	cin >> source >> dest;
	fill(visited, visited + 500, false);
	fill(totalLength, totalLength + 500, inf);
	fill(totalTime, totalTime + 500, inf);
	fill(shortestPreNode, shortestPreNode + 500, -1);
	totalTime[source] = 0;
	totalLength[source] = 0;
	for (int i = 0; i < vertexNum; i++) {
		int u = -1, minDis = inf;
		for (int j = 0; j < vertexNum; j++) {
			if (!visited[j] && totalLength[j] < minDis) {
				u = j;
				minDis = totalLength[j];
			}
		}
		if (u == -1) {
			break;
		}
		visited[u] = true;
		for (int v = 0; v < vertexNum; v++) {
			if (!visited[v] && map[u][v].length != inf) {
				if (totalLength[u] + map[u][v].length < totalLength[v]) {
					shortestPreNode[v] = u;
					totalTime[v] = totalTime[u] + map[u][v].time;
					totalLength[v] = totalLength[u] + map[u][v].length;
				}
				else if (totalLength[u] + map[u][v].length == totalLength[v]) {
					if (totalTime[v] > totalTime[u] + map[u][v].time) {
						shortestPreNode[v] = u;
						totalTime[v] = totalTime[u] + map[u][v].time;
					}
				}
			}
		}
	}
	vector<int> shortest;
	int cur = dest;
	while (cur != -1) {
		shortest.push_back(cur);
		cur = shortestPreNode[cur];
	}

	fill(fastestPreNode, fastestPreNode + 500, -1);
	fill(totalTime, totalTime + 500, inf);
	totalTime[source] = 0;
	fill(visited, visited + 500, false);
	fill(totalVertex, totalVertex + 500, inf);
	totalVertex[source] = 1;
	for (int i = 0; i < vertexNum; i++) {
		int u = -1, minTime = inf;
		for (int j = 0; j < vertexNum; j++) {
			if (!visited[j] && totalTime[j] < minTime) {
				minTime = totalTime[j];
				u = j;
			}
		}
		if (u == -1) {
			break;
		}
		visited[u] = true;
		for (int v = 0; v < vertexNum; v++) {
			if (!visited[v] && map[u][v].time != inf) {
				if (totalTime[u] + map[u][v].time < totalTime[v]) {
					fastestPreNode[v] = u;
					totalVertex[v] = totalVertex[u] + 1;
					totalTime[v] = totalTime[u] + map[u][v].time;
				}
				else if (totalTime[u] + map[u][v].time == totalTime[v]) {	//不同路径到达结点v的时间相等
					if (totalVertex[v] > totalVertex[u] + 1) {	//当前路径经过的结点数更少
						totalVertex[v] = totalVertex[u] + 1;
						fastestPreNode[v] = u;
					}
				}
			}
		}
	}
	cur = dest;
	vector<int> fastest;
	while (cur != -1) {
		fastest.push_back(cur);
		cur = fastestPreNode[cur];
	}

	if (fastest == shortest) {
		printf("Distance = %d; Time = %d: ", totalLength[dest], totalTime[dest]);
		for (int i = shortest.size() - 1; i >= 0; i--) {
			cout << shortest[i];
			if (i != 0) {
				cout << " -> ";
			}
		}
		cout << endl;
	}
	else {
		printf("Distance = %d: ", totalLength[dest]);
		for (int i = shortest.size() - 1; i >= 0; i--) {
			cout << shortest[i];
			if (i != 0) {
				cout << " -> ";
			}
		}
		cout << endl;
		printf("Time = %d: ", totalTime[dest]);
		for (int i = fastest.size() - 1; i >= 0; i--) {
			cout << fastest[i];
			if (i != 0) {
				cout << " -> ";
			}
		}
		cout << endl;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值