1030旅行プラン(30ポイント)
旅行者のマップは一緒に、各高速道路のコストで、高速道路に沿って都市間の距離を提供します。今、あなたは彼/彼女の開始都市と目的地間の最短経路を決定するために旅行者を支援するプログラムを書くことになっています。そのような最短経路が一意でない場合、あなたは一意であることが保証される最小のコスト、と一つの出力になっています。
入力仕様:
各入力ファイルには、1つのテストケースが含まれています。各ケース4つの正の整数を含む行から始まるN、M、S、およびD、N(≤500)は都市の数である(したがって、都市が0から番号付けされるNを -1)。Mは、高速道路の数です。S及びDは、それぞれ、開始および宛先の都市です。次に、M個の行の形式は、各高速道路の情報を提供し、次のとおりです。
City1 City2 Distance Cost
数字は、これ以上の500以上のすべての整数ではない、とスペースで分離されます。
出力仕様:
各テストケースのために、印刷が一列に目的地までの開始点から最短経路に沿った都市が、合計距離および経路の総コストが続きます。数字はスペースで区切る必要があり、出力の末尾に余分なスペースがあってはなりません。
サンプル入力:
4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20
サンプル出力:
0 2 3 3 40
分析:最短パスダイクストラ/ダイクストラ+ DFSは(「アルゴリズムノート」P386-P391を参照してください)
要件:最短経路、最短ルートが最も小さい部分を過ごすための唯一の選択肢ではない場合
出力:起点 途径城市 终点 最短路径长度 最短路径花费
- 市コード:0 N-1へ
- 無向グラフ
ご注意ください
- トピックについての図は、時には質問の意味が不明確であることを理解する、時間の一部のACで、無向グラフ/有向グラフかどうかを検討してください。
私はもともと入力街に言及したトピックは、市内の終わりに出発点があるので、それは、有向グラフだと思ったこの質問は、結果は無向グラフです。。
最短パスのアイデア:
コード
最初:メインダイクストラ法(最初は、この質問のために、より便利です)
ダイクストラ最短パスと最小コストを見つけるためのアルゴリズム、DFS再帰出力ノード最短パス経路
/*Dijkstra算法*/
#include<iostream>
#include<vector>
using namespace std;
const int maxN=510;
const int INF=1000000000;
struct Node {
int cityNo,dis,cost;//Adj[u][j].dis 表示u到j的边权,cost表示该边的花费
};
vector<Node> Adj[maxN];//邻接表实现 有向权图
int pre[maxN];//pre[u] 最短路径上u的前驱结点
int distan[maxN];//distan[u] S到u的最短距离
int Cost[maxN];//Cost[u] S到u的最少花费
bool vis[maxN];
int N,M,S,D;
void Dijkstra() {
fill(vis,vis+maxN,false);
fill(distan,distan+maxN,INF);
fill(Cost,Cost+maxN,INF);
// for(int i=0; i<N; i++) pre[i]=i; //为什么pre需要赋初始值???不赋值可以吗
distan[S]=0;
Cost[S]=0;
for(int k=0; k<N; k++) {
//找未访问过且最小的distan[u]
int u=-1;
int minDistan=INF;
for(int i=0; i<N; i++) {
if(vis[i]==false&&distan[i]<minDistan) {
u=i;
minDistan=distan[i];
}
}
if(u==-1) return;//S没有临界点,结束
vis[u]=true;
struct Node v;
for(int i=0; i<Adj[u].size(); i++) { //遍历所有与u邻接的点
v=Adj[u][i];
int vNo=v.cityNo;
if(vis[vNo]==false) {
if(distan[u]+v.dis<distan[vNo]) {//最优解
distan[vNo]=distan[u]+v.dis;
Cost[vNo]=Cost[u]+v.cost;
pre[vNo]=u;
} else if(distan[u]+v.dis==distan[vNo]) { //多条最短路径
if(Cost[u]+v.cost<Cost[vNo]) { //选择花费更少的
Cost[vNo]=Cost[u]+v.cost;
pre[vNo]=u;
}
}
}
}
}
}
//递归输出最短路径的结点
void DFS(int now) { //now为当前访问的顶点(从终点开始递归)
if(now==S) { //到达终点S
printf("%d ",S);
return;
}
DFS(pre[now]);//递归访问now的前驱结点
printf("%d ",now);//从最深层return回来后,输出每一层的顶点编号
}
int main() {
scanf("%d%d%d%d",&N,&M,&S,&D);
int s,d,dis,ct;
for(int i=0; i<M; i++) {
scanf("%d%d%d%d",&s,&d,&dis,&ct);
Adj[s].push_back({d,dis,ct});
Adj[d].push_back({s,dis,ct});
}
Dijkstra();
DFS(D);
printf("%d %d",distan[D],Cost[D]);
return 0;
}
第二:ダイクストラのアルゴリズム+ DFS
最短経路を見つけるためのダイクストラのアルゴリズムでは、DFSは最短経路を取る以上のパスを見つけ、ルートノードを保存します
/*Dijkstra算法+DFS*/
#include<iostream>
#include<vector>
using namespace std;
const int maxN=510;
const int INF=1000000000;
struct Node {
int cityNo,dis;//Adj[u][j].dis 表示u到j的边权
};
vector<Node> Adj[maxN];//邻接表实现 有向权图
int cost[maxN][maxN];//cost[u][v] 点u到点v的花费
vector<int> pre[maxN];//pre[u] 最短路径上u的前驱结点(若有多条最短路径则有多个前驱)
int distan[maxN];//distan[u] S到u的最短距离
bool vis[maxN];
int N,M,S,D;
void Dijkstra() {
fill(vis,vis+maxN,false);
fill(distan,distan+maxN,INF);
distan[S]=0;
for(int k=0; k<N; k++) {
//找未访问过且最小的distan[u]
int u=-1;
int minDistan=INF;
for(int i=0; i<N; i++) {
if(vis[i]==false&&distan[i]<minDistan) {
u=i;
minDistan=distan[i];
}
}
if(u==-1) return;//S没有临界点,结束
vis[u]=true;
struct Node v;
for(int i=0; i<Adj[u].size(); i++) { //遍历所有与u邻接的点
v=Adj[u][i];
int vNo=v.cityNo;
if(vis[vNo]==false) {
if(distan[u]+v.dis<distan[vNo]) {//最优解
distan[vNo]=distan[u]+v.dis;
pre[vNo].clear();
pre[vNo].push_back(u);
} else if(distan[u]+v.dis==distan[vNo]) { //多条最短路径
pre[vNo].push_back(u);
}
}
}
}
}
vector<int> tempPath,path;//倒序存放最短路径的节点
int minCost=INF;
//选择花费最少的最短路径
void DFS(int v) {
if(v==S) {
tempPath.push_back(v);//放入起点,一条最短路径确认完毕
//计算总花费
int tempCost=0;
for(int i=tempPath.size()-1; i>0; i--) {
tempCost+=cost[tempPath[i]][tempPath[i-1]];
}
if(tempCost<minCost) {
minCost=tempCost;
path=tempPath;
}
tempPath.pop_back();
}
tempPath.push_back(v);
for(int i=0; i<pre[v].size(); i++) {
DFS(pre[v][i]);
}
tempPath.pop_back();
}
int main() {
scanf("%d%d%d%d",&N,&M,&S,&D);
int s,d,dis,ct;
for(int i=0; i<M; i++) {
scanf("%d%d%d%d",&s,&d,&dis,&ct);
Adj[s].push_back({d,dis});
Adj[d].push_back({s,dis});
cost[s][d]=ct;
cost[d][s]=ct;
}
Dijkstra();
DFS(D);
for(int i=path.size()-1; i>=0; i--) {//倒序输出最短路径
printf("%d ",path[i]);
}
printf("%d %d",distan[D],minCost);
return 0;
}