[PAT解题报告] All Roads Lead to Rome
又是最短路,dijkstra算法的变种。
(1) 记录最短路条数, 更新的时候:
用k更新i的时候,有两种情况
如果最短路长度相等,num[i] += num[k]
如果最短路更短 num[i] = num[k]
(2) happiness 和 bypass 这两个没的说,如果要更新的话
happiness[i] = b[i] + happiness[k]
bypass[i] = bypass[k] + 1
所以只是在更新上做手脚,别忘记记录pre[i] = k,以方便倒着还原出路径来。
代码:
#include <cstdio>
#include <cstring>
#include <string>
#include <map>
using namespace std;
const int inf = 1000000000;
const int N = 202;
map<string,int> id;
int cost[N],happy[N],bypass[N],num[N],pre[N],n,a[N][N],b[N];
bool mark[N];
string name[N];
char s[10];
void dijkstra(int s) {
for (int i = 0; i < n; ++i) {
cost[i] = bypass[i] = inf;
num[i] = happy[i] = 0;
mark[i] = false;
}
num[s] = 1;
cost[s] = bypass[s] = 0;
pre[s] = -1;
for (int j = 0; j < n; ++j) {
int k = -1;
for (int i = 0; i < n; ++i) {
if ((!mark[i]) && ((k < 0) || (cost[i] < cost[k]))) {
k = i;
}
}
mark[k] = true;
for (int i = 0; i < n; ++i) {
if ((!mark[i]) && (a[k][i] < inf)) {
int temp = cost[k] + a[k][i];
if (temp < cost[i]) {
cost[i] = temp;
happy[i] = happy[k] + b[i];
bypass[i] = bypass[k] + 1;
num[i] = num[k];
pre[i] = k;
}
else if (temp == cost[i]) {
num[i] += num[k];
int mayhappy = happy[k] + b[i];
int maybypass = bypass[k] + 1;
if ((mayhappy > happy[i]) || ((mayhappy == happy[i]) && (maybypass < bypass[i]))) {
happy[i] = mayhappy;
bypass[i] = maybypass;
pre[i] = k;
}
}
}
}
}
}
void print(int x) {
if (x) {
print(pre[x]);
printf("->");
}
printf("%s",name[x].c_str());
}
int main() {
int m;
scanf("%d%d%s",&n,&m,s);
id[name[0] = s] = 0;
b[0] = 0;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
a[i][j] = inf;
}
}
for (int i = 1; i < n; ++i) {
scanf("%s%d",s,&b[i]);
id[name[i] = s] = i;
}
for (;m;--m) {
scanf("%s",s);
int x = id[s];
scanf("%s",s);
int y = id[s];
int z;
scanf("%d",&z);
a[x][y] = a[y][x] = min(a[x][y],z);
}
dijkstra(0);
int x = id["ROM"];
printf("%d %d %d %d\n",num[x],cost[x],happy[x],happy[x] / bypass[x]);
print(x);
puts("");
return 0;
}
原题链接: http://www.patest.cn/contests/pat-a-practise/1087
查看3道真题和解析
