[PAT] A1087 All Roads Lead to Rome
阿新 • • 發佈:2020-07-22
(單源最短路徑;多尺標;記錄路徑條數)
題目大意
從一個城市出發有多條路到達“ROM”,求最佳路徑。首先選擇最短路徑;若最短路徑相同,選擇幸福指數最大的;若還相同,選擇平均幸福指數最大的(平均不包括起點,因為起點沒有幸福指數)。同時還要在第一行輸出最短路徑條數、路徑長度、幸福指數、平均幸福指數;第二行輸出最佳路徑。
思路
Dijkstra演算法。dis[]存放最短路徑長度;nowgethappy[]存放當前幸福指數。用一個數組point存路徑經過的頂點數,point[i]表示從起點到結點i的最佳路徑經過幾個結點。用一個數組num存最短路徑條數,當新路徑比當前最短路徑短時,num[v]=num[u]+Adj[u][i].w;
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; }