(1)题意:
n个城市,每个城市之间有可能有一条路,走过这条路的花费为x,经过每个城市的花费为val,
给出n*n的城市地图,q个查询,每次查询x y城市之间的最短距离。
如果有多条最短路,输出字典序最小的那条。
(2)spfa思路:
path数组记录路径,如果存在多条最短路,就用字符串记录一下最短路,比较一下谁的字典序更大。
用dfs递归查找最短路。
(3)代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
#include<vector>
using namespace std;
const int maxn = 2005;
const int INF = 1e9+10;
int vis[maxn],dis[maxn],mp[maxn][maxn],n,val[maxn],pos,path[maxn];
char s1[maxn],s2[maxn];
void dfs(int x,char *ss){
if(x==-1) return ;
dfs(path[x],ss);
ss[pos++] = (char)x;
}
bool cmp(int p1,int p2){ //p1表示原来的,p2表示现在的
pos = 0;
dfs(p1,s1);
s1[pos] = '\0';
pos = 0;
dfs(p2,s2);
s2[pos++] = (char)p1;
s2[pos] = '\0';
return strcmp(s1,s2)>0;
}
void Print(int x){
if(x==-1) return ;
Print(path[x]);
if(path[x]==-1) printf("%d",x);
else printf("-->%d",x);
}
void spfa(int st,int ed){
for(int i=0;i<=n;i++){
vis[i] = 0;dis[i] = INF;path[i] = -1;
}
dis[st] = 0;
queue <int> q;
q.push(st);
while(!q.empty()){
int x = q.front();q.pop();vis[x] = 0;
for(int i=1;i<=n;i++)
if(mp[x][i]!=INF){
if(dis[i]>dis[x]+mp[x][i]+val[i]){
dis[i] = dis[x]+mp[x][i]+val[i];
path[i] = x;
if(vis[i]==0){
vis[i] = 1;
q.push(i);
}
}
else if(dis[i]==dis[x]+mp[x][i]+val[i]&&cmp(i,x)){//原来走到第一个i,现在走到第二个i
path[i] = x;
if(vis[i]==0){
vis[i] = 1;
q.push(i);
}
}
}
}
printf("From %d to %d :\n",st,ed);
printf("Path: ");
Print(ed);
printf("\n");
printf("Total cost : %d\n\n",dis[ed]);
}
int main(void){
while(~scanf("%d",&n)&&n!=0){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
scanf("%d",&mp[i][j]);
if(mp[i][j]==-1) mp[i][j] = INF;
}
}
for(int i=1;i<=n;i++) scanf("%d",&val[i]);
int x,y;
while(~scanf("%d%d",&x,&y)){
if(x==-1&&y==-1){
break;
}
int tp1 = val[x],tp2 = val[y];
val[x] = val[y] = 0;
spfa(x,y);
val[x] = tp1;val[y] = tp2;
}
}
return 0;
}
(4)Ford思路:
用path[i][j]数组记录路径i到j路径上的经过的第一个节点,然后不断更新这个节点,得到最终的路径。
(感觉这题就是为Ford出的)。
(5)代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 2005;
const int INF = 1e9+10;
int mp[maxn][maxn],path[maxn][maxn],n,val[maxn];
void Ford(){
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
int tp = mp[i][k]+mp[k][j]+val[k];
if(mp[i][j]>tp){
mp[i][j] = tp;
path[i][j] = path[i][k];
}
else if(mp[i][j]==tp&&path[i][j]>path[i][k]){
path[i][j] = path[i][k];
}
}
}
}
}
int main(void){
while(~scanf("%d",&n)&&n){
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
scanf("%d",&mp[i][j]);
if(mp[i][j]==-1) mp[i][j] = INF;
path[i][j] = j;
}
for(int i=1;i<=n;i++) scanf("%d",&val[i]);
Ford();
int x,y;
while(~scanf("%d%d",&x,&y)){
if(x==-1&&y==-1) break;
//int t1 = val[x],t2 = val[y];
//val[x] = val[y] = 0;
printf("From %d to %d :\n",x,y);
printf("Path: ");
int tp = x;
while(tp!=y){
printf("%d-->",tp);
tp = path[tp][y];
}
printf("%d\n",y);
printf("Total cost : %d\n\n",mp[x][y]);
//val[x] = t1;val[y] = t2;
}
}
return 0;
}