PAT原题网址PTA | 程序设计类实验辅助教学平台 (pintia.cn)
ACwing原题网址1507. 旅行计划 - AcWing题库
分析
0.易错点
c++
1. 准备
int n, m, Start, End; // 点数 边数 起点编号 终点编号
int g[N][N], c[N][N]; // g存储两点间距离 c存储两点间的花费
int dist[N], cost[N], pre[N];// dist 最终距离 cost最终花费 pre[t]存的是t的前一个点的
bool st[N];
2. 核心
void dijkstra()
{
memset(dist, 0x3f, sizeof dist);
memset(cost, 0x3f, sizeof cost);
// 起点到起点的距离dist为0,还未从起点出发cost = 0
dist[Start] = 0, cost[Start] = 0;
for(int i = 0; i < n; i ++ )
{
int t = -1;
for(int j = 0; j < n; j ++ )
{
if(st[j] == false && (t == -1 || dist[t] > dist[j]) )
t = j;
}
st[t] = true;
for(int j = 0; j < n; j ++ )
{
if(dist[j] > dist[t] + g[t][j])
{
dist[j] = dist[t] + g[t][j];
cost[j] = cost[t] + c[t][j]; // 改变花费
pre[j] = t; // 存j点的前一个点
}
else if(dist[j] == dist[t] + g[t][j] ) // 若距离相等
{
if(cost[j] > cost[t] + c[t][j])
{
cost[j] = cost[t] + c[t][j]; // 更新花费为最小
pre[j] = t; // 存j点的前一个点
}
}
}
}
}
3.main函数
int main()
{
memset(g, 0x3f, sizeof g);//距离
memset(c, 0x3f, sizeof c);//花费 都初始化为0x3f
cin >> n >> m >> Start >> End;// 读入
while(m -- ) // m条边 m次输入
{
int a, b, x, y;
cin >> a >> b >> x >> y;
g[a][b] = g[b][a] = min(g[a][b], x); //存距离
c[a][b] = c[b][a] = min(c[a][b], y); //存花费
}
dijkstra();
for(int i = 0; i < 7; i ++ )
cout << pre[i];// pre下标 0 1 2 3
cout << endl; // 具体值 0 0 0 2 3的前一个点是2 2的前一个点是0
vector<int> path;
for(int i = End; i != Start; i = pre[i] )
path.push_back(i); //path下标 0 1 2 3
// 具体值 3 2 0
cout << path.size();
cout << endl; // 0 - 2 三个点
cout << Start; // 输出起点 0
for(int i = path.size() - 1; i >= 0; i --)
cout << ' ' << path[i]; // 先输出2 再输出3
cout << ' ' << dist[End] << ' ' << cost[End] << endl;
return 0;
}
4. AC代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 600;
int n, m, Start, End; // 点数 边数 起点编号 终点编号
int g[N][N], c[N][N]; // g存储两点间距离 c存储两点间的花费
int dist[N], cost[N], pre[N];// dist 最终距离 cost最终花费 pre[t]存的是t的前一个点的
bool st[N];
void dijkstra()
{
memset(dist, 0x3f, sizeof dist);
memset(cost, 0x3f, sizeof cost);
// 起点到起点的距离dist为0,还未从起点出发cost = 0
dist[Start] = 0, cost[Start] = 0;
for(int i = 0; i < n; i ++ )
{
int t = -1;
for(int j = 0; j < n; j ++ )
{
if(st[j] == false && (t == -1 || dist[t] > dist[j]) )
t = j;
}
st[t] = true;
for(int j = 0; j < n; j ++ )
{
if(dist[j] > dist[t] + g[t][j])
{
dist[j] = dist[t] + g[t][j];
cost[j] = cost[t] + c[t][j]; // 改变花费
pre[j] = t; // 存j点的前一个点
}
else if(dist[j] == dist[t] + g[t][j] ) // 若距离相等
{
if(cost[j] > cost[t] + c[t][j])
{
cost[j] = cost[t] + c[t][j]; // 更新花费为最小
pre[j] = t; // 存j点的前一个点
}
}
}
}
}
int main()
{
memset(g, 0x3f, sizeof g);//距离
memset(c, 0x3f, sizeof c);//花费 都初始化为0x3f
cin >> n >> m >> Start >> End;// 读入
while(m -- ) // m条边 m次输入
{
int a, b, x, y;
cin >> a >> b >> x >> y;
g[a][b] = g[b][a] = min(g[a][b], x); //存距离
c[a][b] = c[b][a] = min(c[a][b], y); //存花费
}
dijkstra();
for(int i = 0; i < 7; i ++ )
cout << pre[i];// pre下标 0 1 2 3
cout << endl; // 具体值 0 0 0 2 3的前一个点是2 2的前一个点是0
vector<int> path;
for(int i = End; i != Start; i = pre[i] )
path.push_back(i); //path下标 0 1 2 3
// 具体值 3 2 0
cout << path.size();
cout << endl; // 0 - 2 三个点
cout << Start; // 输出起点 0
for(int i = path.size() - 1; i >= 0; i --)
cout << ' ' << path[i]; // 先输出2 再输出3
cout << ' ' << dist[End] << ' ' << cost[End] << endl;
return 0;
}