PAT甲级1087 All Roads Lead to Rome (30 分)题解

在这里插入图片描述在这里插入图片描述
\quad 这个题需要考虑很多因素,第一要求是找出花费最少的路,同时统计这些路的条数;第二要求是在花费相同情况下找出happy值最高的路,第三要求是在花费和happy值都相同的情况下找出平均happy值最高的路,即经过最少的站点。故需要在子结构中层层判断并更新相应的数值。题目还要求我们输出这条路的路径,故需要一个数组path保存当前节点是由哪一个节点过来的。对了,我们还需要建立从名称到数字的映射和数字到名称的映射,这样方便我们用数字表示每个地方,程序如下:

#include <iostream>
#include <vector>
#include <map>
#include <queue>
#include <stack>
#include <cstring>
using namespace std;
const int maxn = 201;
vector<pair<int, int> > E[maxn]; 
int vis[maxn], dis[maxn], path[maxn];
int happy[maxn], happySum[maxn], num[maxn];  // 花费,happy值,经过的站点数量
int routes[maxn];  // 起点到该点最短路径条数
map<string ,int> mp;  // 地名到索引的映射
map<int, string> rmp; // 索引到地名的映射
void Dijistra(int s, int t)
{
	fill(dis, dis+maxn, 0x3f3f3f3f);
	dis[s] = 0;
	priority_queue<pair<int, int> > q;
	q.push({0, s});
	num[s] = 0;
	happySum[s] = happy[s];
	routes[s] = 1;
	while(!q.empty())
	{
		int u = q.top().second;
		q.pop();
		if(vis[u]==1) continue;
		vis[u] = 1;
		for (int i = 0; i < E[u].size(); ++i)
		{
			int v = E[u][i].first, w = E[u][i].second;
			if(dis[v]>dis[u]+w)
			{
				dis[v] = dis[u]+w;
				path[v] = u;
				happySum[v] = happySum[u]+happy[v];
				num[v] = num[u]+1;
				routes[v] = routes[u];
				if(vis[v]==0) q.push({-dis[v], v});
			}
			else if(dis[v]==dis[u]+w)
			{
				routes[v] += routes[u];
				if(happySum[v]<happySum[u]+happy[v])
				{
					path[v] = u;
					happySum[v] = happySum[u]+happy[v];
					num[v] = num[u]+1;
					if(vis[v]==0) q.push({-dis[v], v});
				}
				else if(happySum[v]==happySum[u]+happy[v] && num[v]>num[u]+1)
				{
					path[v] = u;
					num[v] = num[u]+1;
					if(vis[v]==0) q.push({-dis[v], v});
				}
			}
		}
	}
	int avg = happySum[t]/num[t];
	cout << routes[t] << " " << dis[t] << " " << happySum[t] << " " << avg << endl;
}
void getPath(int s, int t)  // 从path数组中获取
{
	stack<int> st;
	st.push(t);
	t = path[t];
	while(t!=s)
	{
		st.push(t);
		t = path[t];
	}
	st.push(s);
	while(!st.empty())
	{
		cout << rmp[st.top()];
		st.pop();
		if(st.size()) cout << "->";
	}
}
int main(int argc, char const *argv[])
{
	int N, K; cin >> N >> K;
	string start; cin >> start;
	mp[start] = 0; rmp[0]=start;
	int t;  // 终点ROM的编号
	for(int i = 1; i < N; i++)
	{
		string s; int temp;
		cin >> s >> temp;
		if(s=="ROM") t = i;
		happy[i] = temp;
		mp[s] = i;
		rmp[i] = s;
	}
	while(K--)
	{
		string u, v; int w;
		cin >> u >> v >> w;
		E[mp[u]].push_back({mp[v], w});
		E[mp[v]].push_back({mp[u], w});
	}
	Dijistra(0, t);
	getPath(0, t);
	return 0;
}
已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页