PTA最短路天梯地图(30分)

Posted 行码棋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PTA最短路天梯地图(30分)相关的知识,希望对你有一定的参考价值。

题目链接:
https://pintia.cn/problem-sets/994805046380707840/problems/994805051153825792

给你一张图,每条边有长度和通过时间,让你找最短长度和最短时间。
要求:
若最短时间的路径有多条,找最短的那条
若最短长度的路径有多条,找最少节点的那条
若两条路径的路线一样,输出一条即可


这道题判断特殊情况有点恶心,确实不是很好做

dis[]数组分别记录最短长度的数组和最短时间的数组,两个共用一个
f[]记录路径中的节点数目,在求最短长度用到
g[]记录路径中的长度,再求最短时间用到

f[],g[]数组都是在求最短路的过程中用到的,是记录能够当前已经遍历到路径的信息。
比如说求最短时间时,g[]记录的是最短时间路径中的最短长度(在最短时间的这几条路径中的相对最短长度),而非最短长度。

在两次最短路的过程中,用vector数组记录下路径,最后对路径进行比较即可

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 505, M = N * N * 2;

ll e[M], w[M], t[M], h[N], ne[M], idx, f[N], g[N];
int n, m;
ll dis[N], pre[N];
bool vis[N];

vector<int> a, b;
int res_l, res_t;

void add(int a, int b, int c, int d)

	e[idx] = b, w[idx] = c, t[idx] = d, ne[idx] = h[a], h[a] = idx++;


void print_l(int x)

	if(pre[x] == 0)
	
		b.push_back(x);
		return;
	
	print_l(pre[x]);
	b.push_back(x);

void print_t(int x)

	if(pre[x] == 0)
	
		a.push_back(x);
		return;
	
	print_t(pre[x]);
	a.push_back(x);


void dijkstra_l(int s, int d)

	memset(dis, 0x3f, sizeof dis);
	memset(vis, false, sizeof vis);
	memset(pre, 0, sizeof pre);
	fill(f + 1, f + 1 + n, 1);
	dis[s] = 0;
	priority_queue<pair<int, int>> q;

	q.push(0, s);
	while(!q.empty())
	
		pair<int, int> t = q.top();
		q.pop();
		if(vis[t.second]) continue;
		vis[t.second] = true;

		int u = t.second;
		for(int i = h[u]; ~i; i = ne[i])
		
			int v = e[i];
			if(dis[v] > dis[u] + w[i])
			
				f[v] = f[u] + 1;
				dis[v] = dis[u] + w[i];
				q.push(-dis[v], v);
				pre[v] = u;
			
			else if(dis[v] == dis[u] + w[i])
			
				if(f[v] > f[u] + 1)
				
					f[v] = f[u] + 1;
					pre[v] = u;
				
			
		
	

	res_l = dis[d];
	print_l(d);

void dijkstra_t(int s, int d)

	memset(dis, 0x3f, sizeof dis);
	memset(vis, false, sizeof vis);
	memset(pre, 0, sizeof pre);
	fill(f + 1, f + 1 + n, 0x3f3f3f3f);
	f[s] = 0;
	dis[s] = 0;
	priority_queue<pair<int, int>> q;

	q.push(0, s);
	while(!q.empty())
	
		pair<int, int> tt = q.top();
		q.pop();
		if(vis[tt.second]) continue;
		vis[tt.second] = true;

		int u = tt.second;
		for(int i = h[u]; ~i; i = ne[i])
		
			int v = e[i];
			if(dis[v] > dis[u] + t[i])
			
				dis[v] = dis[u] + t[i];
				f[v] = f[u] + w[i];
				q.push(-dis[v], v);
				pre[v] = u;
			
			else if(dis[v] == dis[u] + t[i])
			
				if(f[v] > f[u] + w[i])
				
					f[v] = f[u] + w[i];
					pre[v] = u;
				
			
		
	

	res_t = dis[d];
	print_t(d);

int main()

	ios::sync_with_stdio(false);
	cin.tie(0);

	cin >> n >> m;

	memset(h, -1, sizeof h);
	for(int i = 1; i <= m; i++)
	
		int u, v, f, dd, tt;
		cin >> u >> v >> f >> dd >> tt;

		if(f == 1)
			add(u, v, dd, tt);
		else 
		
			add(u, v, dd, tt);
			add(v, u, dd, tt);
		
	
	int s, d;
	cin >> s >> d;
	dijkstra_l(s, d);
	memcpy(g, dis, sizeof dis);
	dijkstra_t(s, d);

	bool is = true;
	if(a.size() == b.size())
	
		for(int i = 0; i < int(a.size()); i++)
			
				if(a[i] != b[i])
					is = false;
			
	
	else is = false;

	if(is) 
	
		cout << "Time = " << res_t << "; Distance = " << res_l << ": ";
		for(int i = 0; i < int(a.size()); i++)
		
			if(i) cout << " => ";
			cout << a[i];
		
	
	else
	
		cout << "Time = " << res_t << ": ";
		for(int i = 0; i < int(a.size()); i++)
		
			if(i) cout << " => ";
			cout << a[i];
		
		cout << "\\n";
		cout << "Distance = " << res_l << ": ";
		for(int i = 0; i < int(b.size()); i++)
		
			if(i) cout << " => ";
			cout << b[i];
		
	
	return 0;

以上是关于PTA最短路天梯地图(30分)的主要内容,如果未能解决你的问题,请参考以下文章

进阶实验6-3.3 天梯地图 (30分)-Dijkstra

PTA天梯赛L2

PTA团体程序设计天梯赛-练习集 25分的题

L3-007 天梯地图(30 分)

PTA 程序设计天梯赛(41~60题)

PTA 程序设计天梯赛(21~40题)