1087 All Roads Lead to Rome (30分)

1.需从最后向前存储,仅仅记录一条路径

2.从前往后存储会超时,但是的确仅记录一条路径,至于为什么会超时  还没找出原因

3.路径条数和该路线节点数用数组存即可 即若有更小路径,则选择更小路径,路径条数和上一节点路径条数一样,节点数+1,若路径长度相等,则该节点路径数+1,更新最大快乐值

4.优先队列,注意排序规则

5.如果到达终点,注意不要用终点开始遍历,不然会给后序遍历造成麻烦

6.遍历过得点就不需要在来一次(因为遍历的点的选取是有优先顺序的)

#include <iostream>
#include <vector>
#include <cstring>
#include<map>
#include <queue>
#include<stack>
#include <algorithm>
using namespace std;

const int maxn = 200+5;
typedef pair<int, int> P;
vector<P> E[maxn];
int pre[maxn], nxt[maxn];
int vis[maxn], dis[maxn], H[maxn], SH[maxn], Nm[maxn], Sn[maxn];
map<string, int>M;
string MM[maxn];
int n, m;
struct cmp {
	bool operator()(const P p1, const P p2) {
		return p1.first > p2.first; //距离小值优先
	}
};
void Dijistra(int s) {
	bool flag = false;
	memset(vis, 0, sizeof(vis));
	fill(dis, dis+maxn, 0x3f3f3f3f);
	for(int i=0; i<maxn; i++) {
		SH[i] = 0;
		Nm[i] = 0;
		Sn[i] = 0;
	}
	dis[s] = 0;
	Nm[s] = 1;
//	SH[s] = H[s];
	priority_queue<P, vector<P>, cmp> q;
	q.push({0, s});
	while(!q.empty()) {
		int u = q.top().second;
		q.pop();
		if(vis[u]==1) continue;
		if(MM[u]== "ROM"){
			flag = true;
			continue;
		}
		vis[u] = 1;
//		cout << "以" << MM[u] << "为起始点:" << endl; 
		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) {
	//			cout << MM[v] << "更新最短路径" << endl;
				nxt[u]=v;
				pre[v] = u;
				Nm[v] = Nm[u];
				Sn[v] = Sn[u]+1;
				SH[v] = SH[u]+H[v];
				dis[v] = dis[u]+w;
				if(vis[v]==0) q.push({dis[v], v});
			} else if(dis[v]==dis[u]+w) {
	//			cout<< MM[v] << "最短距离一样 " << endl;
				Nm[v] += Nm[u];
	//			cout << v << "---" << Nm[v] <<  endl;
				if(SH[v]<SH[u]+H[v]) {
					SH[v] = SH[u]+H[v];
					nxt[u]=v;
					pre[v] = u;
					Sn[v] = Sn[u]+1;
				} else if(SH[v]==SH[u]+H[v]) {
					if(Sn[v]>Sn[u]+1) {
						Sn[v] = Sn[u]+1;
						nxt[u]=v;
						pre[v] = u;
					}
				}
			}
		}
	}
	int End = M["ROM"];

	cout << Nm[End]<< " " << dis[End] << " " << SH[End] << " " << SH[End]/Sn[End] << endl;
	
/*		int i = s;
		while(1) {
			if(i == End) break;
			cout << MM[i] << "->";
			i = nxt[i];
		}
		cout << "ROM" << endl;*/
	stack<int> Sta;
	while(End != s) { //得出路径
		Sta.push(End);
		End = pre[End];
	}
	cout<<MM[s];
	while(!Sta.empty()) {
		cout<<"->"<<MM[Sta.top()];
		Sta.pop();
	}
	cout << endl;
}
int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	string s;
	cin >> n >> m >> s;

	M[s] = 1;
	MM[1] = s;
	for(int i=2; i<=n; i++) {
		string a;
		int w;

		cin >> a >> w;

		M[a] = i;
		MM[i] = a;
		H[i] = w;
//		cout << a << "==>" << M[a] << endl;
	}
	for(int i=1; i<=m; i++) {
		string a1, b1;
		int w;
		cin >> a1 >> b1 >> w;
		int u = M[a1], v = M[b1];
//		cout << m<< a1 << "==>" << u << endl<< b1  << "==>" << v << endl;
		E[u].push_back({v, w});
		E[v].push_back({u, w});
	}
	Dijistra(M[s]);

	return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值