题目:
Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司。该航空公司一共在n个城市设有业务,设这些城市分别标记为0到n-1,一共有m种航线,每种航线连接两个城市,并且航线有一定的价格。Alice和Bob现在要从一个城市沿着航线到达另一个城市,途中可以进行转机。航空公司对他们这次旅行也推出优惠,他们可以免费在最多k种航线上搭乘飞机。那么Alice和Bob这次出行最少花费多少?
思路:
典型的分层图求最短路问题,这类问题一般适用于我们要对图中的某些边的权进行变换的情况,当然变换的次数要很小才行。
d[u][j]表示到达u点已经免费乘坐了j次航线的最短距离。在套一个裸的迪杰斯特拉算法就可以了。
代码:
//#include <bits/stdc++.h> #include <cstdio> #include <cstring> #include <iostream> #include <vector> #include <algorithm> #include <queue> #define MAX 1000000000 #define inf 0x3f3f3f3f #define FRE() freopen("in.txt","r",stdin) using namespace std; typedef long long ll; const int maxn = 10005; int n,m,k,s,t; int d[maxn][15]; struct Edge { int to,c; }; vector<Edge> mp[maxn]; struct Node { int u,k,d; bool operator<(const Node& rhs)const{ return d>rhs.d; } }; void Dij() { for(int i=0; i<=k; i++) d[s][i] = 0; priority_queue<Node> que; que.push(Node{s,0,0}); while(!que.empty()) { Node u = que.top(); que.pop(); if(u.d>d[u.u][u.k]) continue; for(int i=0; i<mp[u.u].size(); i++) { Edge e = mp[u.u][i];//可以将这里的分层图看做是dp来理解 if(u.d+e.c<d[e.to][u.k])//不乘坐免费的情况 { d[e.to][u.k] = u.d+e.c; que.push(Node{e.to,u.k,u.d+e.c}); } if(u.k+1<=k && d[e.to][u.k+1]>d[u.u][u.k])//免费乘坐的情况 { d[e.to][u.k+1] = d[u.u][u.k]; que.push(Node{e.to,u.k+1,d[u.u][u.k]}); } } } return ; } int main() { //FRE(); memset(d,inf,sizeof(d)); scanf("%d%d%d",&n,&m,&k); scanf("%d%d",&s,&t); for(int i=0; i<m; i++) { int u,v,c; scanf("%d%d%d",&u,&v,&c); mp[u].push_back(Edge{v,c}); mp[v].push_back(Edge{u,c}); } Dij(); int ans = inf; for(int i=0; i<=k; i++) { ans = min(ans,d[t][i]); } printf("%d ",ans); return 0; }