题目链接: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;
}