PAT A1030 Travel Plan (30 分)
直接采用Dijkstra算法
#include<iostream>
#include<vector>
#include<cstdio>
using namespace std;
const int INF=1000000;
int dis[500][500],mindis[500],cost[500][500],mincost[500],pre[500];//从左至右依次表示【两个城市之间的距离】,【两个城市之间的最短距离】,【两个城市之间的花费】,【两个城市之间的最少花费】,【符合要求的直接前驱】
bool vis[500]={false};
vector<int> v[500];
int N,M,S,D;
void Dijkstra(int S){
fill(mindis,mindis+500,INF);
fill(mincost,mincost+500,INF);
mindis[S]=0;
mincost[S]=0;
for(int i=0;i<N;i++){
int u=-1,MIN=INF;
for(int j=0;j<N;j++){
if(vis[j]==false&&mindis[j]<MIN){
MIN=mindis[j];
u=j;
}
}
if(u==-1)return;
vis[u]=true;
for(int i=0;i<v[u].size();i++){
int j=v[u][i];
if(vis[j]==false){
if(mindis[u]+dis[u][j]<mindis[j]){
mindis[j]=mindis[u]+dis[u][j];
mincost[j]=mincost[u]+cost[u][j];
pre[j]=u;
}
else if(mindis[u]+dis[u][j]==mindis[j]){
if(mincost[u]+cost[u][j]<mincost[j]){
mincost[j]=mincost[u]+cost[u][j];
pre[j]=u;
}
}
}
}
}
}
void DFS(int v){
if(v==S){
printf("%d ",v);
return;
}DFS(pre[v]);
printf("%d ",v);
}
int main(){
int i,j,k,l,c;
cin>>N>>M>>S>>D;
for(i=0;i<M;i++){
cin>>j>>k>>l>>c;
v[k].push_back(j);
v[j].push_back(k);
dis[j][k]=dis[k][j]=l;
cost[j][k]=cost[k][j]=c;
}
Dijkstra(S);
DFS(D);
printf("%d %d",mindis[D],mincost[D]);
return 0;
}
采用Dijkstra算法求出最短路径后,再通过DFS对第二标尺进行二次判定
#include<iostream>
#include<vector>
#include<cstdio>
using namespace std;
const int INF=1000000;
int dis[500][500],mindis[500],cost[500][500];
int mincost=INF;//最少花费
bool vis[500]={false};
vector<int> v[500];
vector<int> pre[500];
vector<int> temppath,path;//临时路径,最优路径
int N,M,S,D;
void Dijkstra(int S){
fill(mindis,mindis+500,INF);
mindis[S]=0;
for(int i=0;i<N;i++){
int u=-1,MIN=INF;
for(int j=0;j<N;j++){
if(vis[j]==false&&mindis[j]<MIN){
MIN=mindis[j];
u=j;
}
}
if(u==-1)return;
vis[u]=true;
for(int i=0;i<v[u].size();i++){
int j=v[u][i];
if(vis[j]==false){
if(mindis[u]+dis[u][j]<mindis[j]){
mindis[j]=mindis[u]+dis[u][j];
pre[j].clear();
pre[j].push_back(u);
}
else if(mindis[u]+dis[u][j]==mindis[j]){
pre[j].push_back(u);
}
}
}
}
}
void DFS(int v){
temppath.push_back(v);
if(v==S){
int tempcost=0;
for(int i=temppath.size()-1;i>0;i--){
int id=temppath[i],idNext=temppath[i-1];
tempcost+=cost[id][idNext];
}
if(tempcost<mincost){
mincost=tempcost;
path=temppath;
}
temppath.pop_back();
return;
}
for(int i=0;i<pre[v].size();i++){
DFS(pre[v][i]);
}
temppath.pop_back();
}
int main(){
int i,j,k,l,c;
cin>>N>>M>>S>>D;
for(i=0;i<M;i++){
cin>>j>>k>>l>>c;
v[k].push_back(j);
v[j].push_back(k);
dis[j][k]=dis[k][j]=l;
cost[j][k]=cost[k][j]=c;
}
Dijkstra(S);
DFS(D);
for(int i=path.size()-1;i>=0;i--){
printf("%d ",path[i]);
}
printf("%d %d",mindis[D],mincost);
return 0;
}
或者从题目出发,直接采用DFS进行递归求解
#include<iostream>
#include<vector>
#include<cstdio>
using namespace std;
const int INF=1000000;
int dis[500][500],mindis[500],cost[500][500],mincost[500];
int mincosttoD=INF;//到达D的最少路径
int mindistoD=INF;//到达D的最短路径
int N,M,S,D;
vector<int>v[500];
vector<int> temppath,path;//临时路径,最优路径
void DFS(int curcity,int curlen,int curcost){
if(curlen>mindis[curcity]) return;
temppath.push_back(curcity);
if(curcity==D){
if(curlen<mindis[D]||(curlen==mindis[D]&&curcost<mincost[D])){
mindistoD=mindis[D]=curlen;
mincosttoD=mincost[D]=curcost;
path=temppath;
}
}
else{
if(curlen<mindis[curcity]){//直接对第一标尺进行判断
mindis[curcity]=curlen;
}
for(int o: v[curcity]){
DFS(o,curlen+dis[o][curcity],curcost+cost[o][curcity]);
}
}
temppath.pop_back();
}
int main(){
int i,j,k,l,c;
cin>>N>>M>>S>>D;
for(i=0;i<M;i++){
cin>>j>>k>>l>>c;
v[k].push_back(j);
v[j].push_back(k);
dis[j][k]=dis[k][j]=l;
cost[j][k]=cost[k][j]=c;
}
fill(mindis,mindis+500,INF);
fill(mincost,mincost+500,INF);
DFS(S,0,0);
for(int i=0;i<path.size();i++){
printf("%d ",path[i]);
}
cout<<mindistoD<<" "<<mincosttoD;
}
或者采用Bellman-Ford算法,其对最短路径的求法和有多重标尺时的做法与Dijkstra算法一致
#include<iostream>
#include<vector>
#include<unordered_set>//采用set或者unordered_set因为Bellman-Ford算法多次访问已经计算过的顶点,以因此用set记录其前驱。
#include<cstdio>
using namespace std;
const int INF=1000000;
int dis[500][500],mindis[500],cost[500][500];
int mincost=INF;//最少花费
bool vis[500]={false};
vector<int> v[500];
unordered_set<int> pre[500];
vector<int> temppath,path;//临时路径,最优路径
int N,M,S,D;
void Bellman(int S){
fill(mindis,mindis+500,INF);
mindis[S]=0;
for(int i=0;i<N-1;i++){
for(int j=0;j<N;j++){
for(int each:v[j]){
if(mindis[j]+dis[j][each]<mindis[each]){
mindis[each]=mindis[j]+dis[j][each];
pre[each].clear();
pre[each].insert(j);
}
else if(mindis[j]+dis[j][each]==mindis[each]){
pre[each].insert(j);
}
}
}
}
}
void DFS(int v){
temppath.push_back(v);
if(v==S){
int tempcost=0;
for(int i=temppath.size()-1;i>0;i--){
int id=temppath[i],idNext=temppath[i-1];
tempcost+=cost[id][idNext];
}
if(tempcost<mincost){
mincost=tempcost;
path=temppath;
}
temppath.pop_back();
return;
}
for(auto i=pre[v].begin();i!=pre[v].end();i++){
DFS(*i);
}
temppath.pop_back();
}
int main(){
int i,j,k,l,c;
cin>>N>>M>>S>>D;
for(i=0;i<M;i++){
cin>>j>>k>>l>>c;
v[k].push_back(j);
v[j].push_back(k);
dis[j][k]=dis[k][j]=l;
cost[j][k]=cost[k][j]=c;
}
Bellman(S);
DFS(D);
for(int i=path.size()-1;i>=0;i--){
printf("%d ",path[i]);
}
printf("%d %d",mindis[D],mincost);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话