1. 程式人生 > 實用技巧 >[PAT] A1087 All Roads Lead to Rome

[PAT] A1087 All Roads Lead to Rome

(單源最短路徑;多尺標;記錄路徑條數)

題目大意

從一個城市出發有多條路到達“ROM”,求最佳路徑。首先選擇最短路徑;若最短路徑相同,選擇幸福指數最大的;若還相同,選擇平均幸福指數最大的(平均不包括起點,因為起點沒有幸福指數)。同時還要在第一行輸出最短路徑條數、路徑長度、幸福指數、平均幸福指數;第二行輸出最佳路徑。

思路

Dijkstra演算法。dis[]存放最短路徑長度;nowgethappy[]存放當前幸福指數。用一個數組point存路徑經過的頂點數,point[i]表示從起點到結點i的最佳路徑經過幾個結點。用一個數組num存最短路徑條數,當新路徑比當前最短路徑短時,num[v]=num[u]+Adj[u][i].w;

; 當num[v]==num[u]+Adj[u][i].wnum[i]時,將u的最短路徑條數累加到v上,即num[v]=num[v]+num[u];。陣列pre[i]表示最短路徑中結點i的前驅,最後遞迴輸出路徑。
建立了一個int到string的map和一個string到int的map,將名字和編號對應起來。

AC程式碼

#define _CRT_SECURE_NO_WARNINGS
#include<cstdio>
#include<iostream>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
#define MAX 205
#define INF 100000000
struct node {
	int v, w;
};
int n, m, ren = 0, s;
vector<node>Adj[MAX];
map<int, string>idtoname;
map<string, int>nametoid;
int happiness[MAX], dis[MAX], nowgethappy[MAX] = { 0 }, point[MAX] = { 0 }, pre[MAX], num[MAX] = { 0 };
bool vis[MAX] = { false };
int addid(string a) {
	int id = ren;
	ren++;
	idtoname[id] = a;
	nametoid[a] = id;
	return id;
}
int Dijkstra(int s) {
	int i, j;
	fill(dis, dis + n, INF);
	for (i = 0;i < n;i++)pre[i] = i;
	dis[s] = 0;
	num[s] = 1;
	for (i = 0;i < n;i++) {
		int min = INF, u = -1;
		for (j = 0;j < n;j++) {
			if (vis[j] == false && dis[j] < min) {
				min = dis[j];
				u = j;
			}
		}
		if (u == -1)return -1;
		vis[u] = true;
		for (j = 0;j < Adj[u].size();j++) {
			int v = Adj[u][j].v;
			if (vis[v] == false) {
				if (dis[v] > dis[u] + Adj[u][j].w) {
					nowgethappy[v] = nowgethappy[u] + happiness[v];
					dis[v] = dis[u] + Adj[u][j].w;
					point[v] = point[u] + 1;
					num[v] = num[u];
					pre[v] = u;
				}
				else if (dis[v] == dis[u] + Adj[u][j].w) {
					num[v] = num[v] + num[u];//注意這裡是把num[u]累加到num[v]上。
					if (nowgethappy[v] < nowgethappy[u] + happiness[v]) {
						nowgethappy[v] = nowgethappy[u] + happiness[v];
						point[v] = point[u] + 1;
						pre[v] = u;
					}
					else if (nowgethappy[v] == nowgethappy[u] + happiness[v]) {
						if (point[v] > point[u] + 1) {
							point[v] = point[u] + 1;
							pre[v] = u;
						}
					}
				}
			}
		}
	}
}
void DFS(int x) {
	if (x == s) {
		cout << idtoname[x];
		return;
	}
	DFS(pre[x]);
	cout << "->" << idtoname[x];
}
int main() {
	int i, happy;
	scanf("%d%d", &n,&m);
	string start;
	cin >> start;
	s = addid(start);
	for (i = 1;i < n;i++) {
		string temp;
		cin >> temp;
		scanf("%d", &happy);
		int id = addid(temp);
		happiness[id] = happy;
	}
	for (i = 0;i < m;i++) {
		string temp1, temp2;
		cin >> temp1 >> temp2;
		node tempn;
		scanf("%d", &tempn.w);
		int id1 = nametoid[temp1], id2 = nametoid[temp2];
		tempn.v = id2;Adj[id1].push_back(tempn);
		tempn.v = id1;Adj[id2].push_back(tempn);
	}
	Dijkstra(s);
	int ending = nametoid["ROM"];
	printf("%d %d %d %d\n", num[ending], dis[ending], nowgethappy[ending], nowgethappy[ending] / (point[ending]));
	DFS(ending);
	return 0;
}