题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1064
不算难,只是代码看起来有点恶心。
首先是用Floyd求各个路口之间的最短路,储存在数组path里。
然后计算任意一个路口 i 与任意一个城市 j 之间最短路经过的第一个路口(即路口 i 和该路口之间有一条边),记录在 shortPath[i][j] 里。
最后看每个路牌,比如从 a 到 b 的路牌,如果路口 a 到人任意一个城市 j 的最短路径经过 b 的话(就是shortPath[a][j] == b),就把城市 j 列在路牌里。
(题目里说假设每对路口之间只有一个最短路径,这是一个非常重要的条件,避免了下列情况:
其中1是城市,从3到1的两条路的路程是相等的,这样shortPath[3][1]就只能记录下0,而不是2。)
#include<iostream> #include<stdlib.h> #include<cstdio> #include<cstring> #include<math.h> using namespace std; const int MAXN = 31; const double ZERO = 0.0001; struct sign { int cityName, distance; }signList[MAXN]; char city[MAXN][MAXN]; int cmp(const void *a1, const void *b1) { sign* a = (sign*)a1; sign* b = (sign*)b1; if (a->distance > b->distance) return 1; else if (a->distance == b->distance) return strcmp(city[a->cityName], city[b->cityName]); else return -1; } int main() { double path[MAXN][MAXN]; double graph[MAXN][MAXN]; int shortPath[MAXN][MAXN]; int cityLocation[MAXN]; int cases; cin>>cases; for (int iCase=1; iCase<=cases; iCase++) { int i, j, k; int a, b; double d; char name[MAXN]; int n, m, cross; cin>>n>>m>>cross; memset(graph,0,sizeof(graph)); memset(cityLocation,255,sizeof(cityLocation)); for (i=0; i<m; i++) { cin>>a>>b>>d; graph[a][b] = graph[b][a] = d; } for (i=0; i<cross; i++) { cin>>a; cityLocation[a] = i; cin>>name; strcpy(city[i],name); } memcpy(path,graph,sizeof(graph)); for (k=0; k<n; k++) //Floyd for (i=0; i<n; i++) if (path[i][k] > ZERO) for (j=0; j<n; j++) if (path[k][j] > ZERO && i!=j) { d = path[i][k] + path[k][j]; if (path[i][j] < ZERO || path[i][j] > d) path[i][j] = d; } for (i=0; i<n; i++) path[i][i] = 0; memset(shortPath,255,sizeof(shortPath)); for (i=0; i<n; i++) //求路口到城市最短路上的第一个路口 for (j=0; j<n; j++) if (cityLocation[j] >= 0) for (k=0; k<n; k++) if (graph[i][k] >= ZERO/*路口 i 和路口 k 之间有一条边*/ && fabs(path[i][j]-path[k][j]-graph[i][k])<ZERO) { shortPath[i][j] = k; break; } if (iCase != 1) cout<<endl; int listNum; int signNum; scanf("%d",&signNum); for (i=0; i<signNum; i++) { cin>>a>>b>>d; if (i != 0) cout<<endl; listNum = -1; for (j=0; j<n; j++) if (cityLocation[j] >= 0 && shortPath[a][j] == b) { signList[++listNum].cityName = cityLocation[j]; signList[listNum].distance = int(path[a][j]-d+ZERO+0.5); } qsort(signList,listNum+1,sizeof(sign),&cmp); for (j=0; j<=listNum; j++) { printf("%-20s",city[signList[j].cityName]); printf("%d\n",signList[j].distance); } } } return 0; }