PAT A1087 All Roads Lead to Rome (30分)(迪杰斯特拉变体应用,梅开二度)

这里只说明关键部分。

有三个优先级,由高到低分别是:

距离、高兴值、平均高兴值。

距离即是最普通的Dijkstra所求的目标。

高兴值是点权变体之一。

平均高兴值可化为求最短路径中的最少结点路径,也属于点权变体之一。

在更新结果的代码中,优先级高的更新的结果要更多。

所有优先级低的更新时必须保证比它更高优先级的结果是一致的。

下面放代码:(PS,怎么感觉最近这么多Dijkstra。。。)

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<map>
using namespace std;
map<string, int> str2int;
map<int, string> int2str;
const int M = 210;
const int INF = INT32_MAX;
int n, e, G[M][M], vertex[M];
int num[M], path[M], dist[M],happy[M],node[M];
bool vis[M];
string start;
int cur = -1;
int change(string city) {
	if (str2int.find(city) != str2int.end()) {
		return str2int[city];
	}
	cur++;
	str2int[city] = cur;
	int2str[cur] = city;
	return cur;
}
void initGraph() {
	fill(G[0],G[0]+M*M,INF);
	cin >> n >> e>>start;
	string c1, c2;
	int idc1, idc2, ele;
	vertex[change(start)] = 0;
	for (int i = 0; i < n-1; i++) {
		cin >> c1 >> ele;
		vertex[change(c1)]=ele;
	}
	for (int i = 0; i < e; i++) {
		cin >> c1 >> c2 >> ele;
		idc1 = change(c1);
		idc2 = change(c2);
		G[idc1][idc2] = G[idc2][idc1] = ele;
	}
}
void Dijkstra() {
	fill(dist,dist+n,INF);
	for (int i = 1; i < n; i++) {
		path[i] = i;
	}
	int s = str2int[start];
	dist[s] = 0;
	num[s] = 1;
	int k, m;
	for (int i = 0; i < n; i++) {
		k = -1, m = INF;
		for (int j = 0; j < n; j++) {
			if (!vis[j] && dist[j]<m) {
				m = dist[j];
				k = j;
			}
		}
		if (k==-1) {
			return;
		} else {
			vis[k] = true;
		}
		for (int j = 0; j < n; j++) {
			if (!vis[j] && G[k][j]!=INF) {
				if (dist[k]+G[k][j]<dist[j]) {
					dist[j] = dist[k] + G[k][j];
					path[j] = k;
					num[j] = num[k];
					happy[j] = happy[k] + vertex[j];
					node[j] = node[k]+1;
				} else if (dist[k] + G[k][j] == dist[j]) {
					num[j] += num[k];
					if (happy[k]+vertex[j]>happy[j]) {
						happy[j] = happy[k] + vertex[j];
						node[j] = node[k] + 1;
						path[j] = k;
					} else if (happy[k] + vertex[j] == happy[j] && node[j] > node[k] + 1) {
						node[j] = node[k] + 1;
						path[j] = k;
					}
				}
			}
		}
	}
}
void printPath(int s,int d,string &r) {
	if (s==d) {
		r.append(int2str[d]);
		r.append("->");
		return;
	}
	printPath(s,path[d],r);
	r.append(int2str[d]);
	r.append("->");
}
int main() {
	initGraph();
	Dijkstra();
	int s = str2int[start];
	int d = str2int["ROM"];
	cout << num[d] <<" "<< dist[d]<<" "<<happy[d]<<" "<<happy[d]/node[d]<<endl;
	string r;
	printPath(s,d,r);
	cout << r.substr(0,r.size()-2);
	int a = 0;
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_Kirito

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值