Alice 和 Bob 现在要乘飞机旅行,他们选择了一家相对便宜的航空公司。该航空公司一共在 n 个城市设有业务,设这些城市分别标记为 0 到 n−1,一共有 m 种航线,每种航线连接两个城市,并且航线有一定的价格。
Alice 和 Bob 现在要从一个城市沿着航线到达另一个城市,途中可以进行转机。航空公司对他们这次旅行也推出优惠,他们可以免费在最多 k 种航线上搭乘飞机。那么 Alice 和 Bob 这次出行最少花费多少?
第一行三个整数 n,m,k,分别表示城市数,航线数和免费乘坐次数。
接下来一行两个整数 s,t,分别表示他们出行的起点城市编号和终点城市编号。
接下来 m 行,每行三个整数 a,b,c,表示存在一种航线,能从城市 a 到达城市 b,或从城市 b 到达城市 a,价格为 c。
输出一行一个整数,为最少花费。
思路:dijkstra优化,动态规划;
核心:假设 i 代表当前节点,j 是免费次数,i - 1 是指当前节点的上一个节点(父节点),w是这两个节点间的价格,dis是到达i节点,用了j次的免费次数所用的最小价格。
// dis(i,j) = min( dis(i-1,j-1), dis(i-1,j)+ w )
就只需要套dijkstra优化的模板,在求最短路时加入上一段的动规来更新数据即可。
代码如下:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e4 + 5;
typedef long long ll;
int n, m, k;
int s, t;
int T;
// 建图
struct node
{
int e, w;
};
vector<node> v[N];
// dijkstra优先队列
struct Node
{
int x, y, cnt; // 分别代表:价格 当前节点 免费的次数
friend bool operator<(Node aa, Node bb)
{
return aa.x > bb.x; // 结构体中,x小的优先级高,即x最小的在最上面
}
};
priority_queue<Node> q;
int dis[N][12]; // 记录最短距离
bool st[N][12]; // 记录是否被遍历过
void dijkstra()
{
dis[s][0] = 0;
q.push({0, s, 0});
while (q.size())
{
Node h = q.top();
q.pop();
int h1 = h.x, h2 = h.y, h3 = h.cnt; // 价格 当前节点 免费次数
if (st[h2][h3]) continue;
st[h2][h3] = true;
// 假设i代表当前节点,j是免费次数,i-1是指当前节点的上一个节点(父节点)(注:注释i,j与下方代码i,j不同,只是方便陈述注释)
// dis(i,j) = min( dis(i-1,j-1), dis(i-1,j)+ w )
for (int i = 0; i < v[h2].size(); i++)
{
int z1 = v[h2][i].e, z2 = v[h2][i].w; // z1:下一个节点 z2:从当前节点(h2)到下一个节点(z1)的价格
if (h3 < k && dis[z1][h3 + 1] > dis[h2][h3]) // 如果还有免费次数,且价格更低,更新数据
{
dis[z1][h3 + 1] = dis[h2][h3];
q.push({dis[z1][h3 + 1], z1, h3 + 1});
}
if (dis[z1][h3] > dis[h2][h3] + z2) // 只要价格更低,直接更新当前数据
{
dis[z1][h3] = dis[h2][h3] + z2;
q.push({dis[z1][h3], z1, h3});
}
}
}
}
void solve()
{
memset(dis, 0x3f, sizeof dis); // 初始化
cin >> n >> m >> k;
cin >> s >> t;
while (m--)
{
int a, b, c;
cin >> a >> b >> c;
v[a].push_back({b, c});
v[b].push_back({a, c});
}
dijkstra();
// 把终点的全部情况遍历一遍
int ans = 0x3f3f3f3f;
for (int i = 0; i <= k; i++)
{
ans = min(ans, dis[t][i]);
}
cout << ans;
}
int main()
{
ios::sync_with_stdio(false), cin.tie(0); // 关闭同步流,可以让输入更快,弊端自行csdn
T = 1;
while (T--)
{
solve();
}
return 0;
}
因篇幅问题不能全部显示,请点此查看更多更全内容