题目大意及思路:
一个人从某个城市去另一个城市,在途经的某个城市(包括起点和终点)要请人吃饭,在每个城市吃饭的花费不同,在每个城市间行走所需费用也不同。现在他在旅途中吃饭最贵的城市请人吃饭,问总的花费最小是多少。
Sample Input
7 8 5
2 3 5 15 4 4 6
1 2 20
1 4 20
1 5 50
2 3 10
3 4 10
3 5 10
4 5 15
6 7 10
1 5
比如这组样例 :从1到5花费最小的路径是1-2-3-5=20+10+10+ 5(1 2 3 5中吃饭最贵的城市为3,花5块钱)=45
解法:很明显的最短路径,但现在多了一个“要吃饭”的点要考虑,我们可以枚举吃饭的点,并求出每个点到吃饭点的距离,这里要注意,必须保证这条路上所有点的点权不得大于吃饭点的权值。最后按照询问的点直接计算即可
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#define INF 999999999
using namespace std;
int host[100],g[100][100],vis[100],dis[100][100],crt[100];
void readcase(int r,int c){
for(int i=1;i<=r;i++){
scanf("%d",&host[i]);
}
for(int i=1;i<=c;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
g[x][y]=z;
g[y][x]=z;
}
}
int spfa(int s,int r){
memset(vis,0,sizeof(vis));
queue<int>que;
while(!que.empty()){
que.pop();
}
que.push(s);
vis[s]=1;
dis[s][s]=0;
while(!que.empty()){
int now=que.front();
que.pop();
vis[now]=0;
for(int i=1;i<=r;i++){
if(g[now][i] <INF&&dis[s][i]>dis[s][now]+g[now][i] && host[now]<=host[s] && host[i] <= host[s] ){
dis[s][i]=dis[s][now]+g[now][i];
if(vis[i]==0){
vis[i]=1;
que.push(i);
}
}
}
}
}
void compute(int r,int q,int c){
for(int i=1;i<=q;i++){
int s,t;
scanf("%d%d",&s,&t);
int ans=INF;
for(int i=1;i<=r;i++){
//cout<<dis[i][s]<<" "<<dis[i][t]<<endl;
if(ans>dis[i][s]+dis[i][t]+host[i]){
ans=dis[i][s]+dis[i][t]+host[i];
}
//cout<<ans<<endl;
}
if(ans<INF){
printf("%d\n",ans);
}
else{
printf("-1\n");
}
}
}
int main()
{
int r,c,q;
int counter=0;
while(~scanf("%d%d%d",&r,&c,&q) && (r!=0 || c!=0 || q!=0)){
if(counter!=0){
printf("\n");
}
counter++;
printf("Case #%d\n",counter);
memset(host,0,sizeof(host));
for(int i=1;i<=r;i++){
for(int j=1;j<=r;j++){
g[i][j]=INF;
}
}
for(int i=1;i<=r;i++){
for(int j=1;j<=r;j++){
dis[i][j]=INF;
}
}
readcase(r,c);
for(int i=1;i<=r;i++){
spfa(i,r);
//cout<<endl;
}
compute(r,q,c);
}
return 0;
}