Hdu 1385(最短路+字典序)

本文深入解析Hdu1385题目,探讨了在给定城市地图上寻找两个城市间最短路径的方法。通过SPFA算法和Ford算法,详细解释了如何在考虑道路费用和城市费用的情况下,找到最短路径并解决多路径字典序最小问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Hdu 1385

 

(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;
}

参考文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值