1030 Travel Plan(30 分)
题目大意
求起点到终点的最短路径最短距离和花费,要求首先路径最短,其次花费最少,要输出完整路径
基本思路
最直接的一道Dij+dfs题目,直接套用算法笔记给出的模板即可解决
代码
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int MAXN=510;
const int INF=1000000000;
int n,m,s,e;
int G[MAXN][MAXN];//邻接矩阵存储这一张图。初始化每个元素为INF,再从题目中读入边的距离
int vis[MAXN];//表示某个顶点是否被访问。初始化所有顶点为未访问
int d[MAXN];//d[u]记录起点到顶点u的最短距离。初始化d[s]=0,其余的d[u]均为INF
vector<int> pre[MAXN];//pre[u]记录从起点到达顶点u的最短路径上的所有前驱节点。不需要初始化
int cost[MAXN][MAXN];//边权。初始化每个元素为INF,再从题目中读入新的边权
//第一标尺
void Dijkstra(){
//初始化相关数据
fill(d,d+MAXN,INF);
d[s]=0;
//将V中的所有顶点放入S
for(int i=0;i<n;i++){
//求出离起点最近的顶点编号u和距离MIN
int u=-1,MIN=INF;
for(int j=0;j<n;j++){
if(vis[j]==false&&d[j]<MIN){
u=j;
MIN=d[j];
}
}
if(u==-1) return;//已经没有顶点可以到达起点,直接返回
else vis[u]=true;//标记u为已访问,把顶点u放入集合S
//开放所有顶点u出发的边。看看有没有通过u使得某个未访问的顶点v的d[v]减小
for(int v=0;v<n;v++){
if(vis[v]==false&&G[u][v]!=INF){
if(d[u]+G[u][v]<d[v]){
d[v]=d[u]+G[u][v];//优化d[v]
pre[v].clear();//清空pre[v]
pre[v].push_back(u);//令v的前驱为u
}
else if(d[u]+G[u][v]==d[v]){
pre[v].push_back(u);//令v的前驱为u
}
}
}
}
}
//第二标尺
int optcost=INF;//边权和的最小值(第二标尺的最优解)
vector<int> bestPath,tempPath;//最优的路径,临时的路径
void DFS(int end){
if(end==s){
tempPath.push_back(end);
int tempcost=0;
for(int i=tempPath.size()-1;i>0;i--){
int u=tempPath[i],v=tempPath[i-1];
tempcost=tempcost+cost[u][v];
}
if(tempcost<optcost){
optcost=tempcost;
bestPath=tempPath;
}
tempPath.pop_back();
return;
}
tempPath.push_back(end);//将当前访问的结点加入临时路径tempPath的最后面
for(int i=0;i<pre[end].size();i++){//对结点end的每一个前驱节点进行递归
DFS(pre[end][i]);
}
tempPath.pop_back();//遍历完所有的前驱结点,将当前的结点end删除
}
int main(){
//读入数据并初始化相关的数据结构
cin>>n>>m>>s>>e;
fill(G[0],G[0]+MAXN*MAXN,INF);
fill(cost[0],cost[0]+MAXN*MAXN,INF);
for(int i=0;i<m;i++){
int u,v,edgedis,edgeweight;
cin>>u>>v>>edgedis>>edgeweight;
G[u][v]=G[v][u]=edgedis;//无向图
cost[u][v]=cost[v][u]=edgeweight;//无向图
}
//对第一标尺进行Dijkstra算法
Dijkstra();
//对第二标尺进行操作
int end=e;
DFS(end);//从终点开始DFS(回溯法)遍历所有路径,选取第二标尺最优的那一条
//输出最优的那条路径和最优的第二标尺
for(int i=bestPath.size()-1;i>=0;i--){
printf("%d ",bestPath[i]);
}
printf("%d %d\n",d[e],optcost);
}