Luogu4568[JLOI2011][分层图] 飞行路线
Luogu4568[JLOI2011][分层图] 飞行路线
题目描述
Alice 和 Bob 现在要乘飞机旅行,他们选择了一家相对便宜的航空公司。该航空公司一共在 \(n\) 个城市设有业务,设这些城市分别标记为 \(0\) 到 \(n-1\),一共有 \(m\) 种航线,每种航线连接两个城市,并且航线有一定的价格。
Alice 和 Bob 现在要从一个城市沿着航线到达另一个城市,途中可以进行转机。航空公司对他们这次旅行也推出优惠,他们可以免费在最多 \(k\) 种航线上搭乘飞机。那么 Alice 和 Bob 这次出行最少花费多少?
sov
分层图板子。考虑每一次使用免费操作的时候,就进入到下一层。也就是说开数组的时候,多开一维记录使用了几次免费转移操作,在spfa/dij的时候,记录点和第几层。
code
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e4 + 10;
const int MAXM = 5e4 + 10;
int ver[MAXM << 1], nxt[MAXM << 1], edge[MAXM << 1], head[MAXN], tot;
inline void add(const int &x, const int &y, const int &z)
{
ver[++tot] = y;
nxt[tot] = head[x];
edge[tot] = z;
head[x] = tot;
}
int d[MAXN][11];
bool v[MAXN][11];
int n, m, k, s, t;
void dij()
{
struct node
{
int x, k, d;
bool operator<(const node b)const
{
return d > b.d;
}
};
priority_queue<node> q;
memset(d, 0x3f, sizeof(d));
q.push({s, 0, 0});
d[s][0] = 0;
while(q.size())
{
node tmp = q.top();
q.pop();
if(v[tmp.x][tmp.k])
continue;
v[tmp.x][tmp.k] = 1;
for(int i = head[tmp.x]; i; i = nxt[i])
{
int y = ver[i], z = edge[i];
if(d[y][tmp.k] > d[tmp.x][tmp.k] + z)
{
d[y][tmp.k] = d[tmp.x][tmp.k] + z;
q.push({y, tmp.k, d[y][tmp.k]});
}
if(tmp.k + 1 <= k && d[y][tmp.k + 1] > d[tmp.x][tmp.k])
{
d[y][tmp.k + 1] = d[tmp.x][tmp.k];
q.push({y, tmp.k + 1, d[y][tmp.k + 1]});
}
}
}
}
void spfa()
{
queue<pair<int,int> > q;
q.push({s, 0});
memset(d, 0x3f, sizeof(d));
d[s][0] = 0;
v[s][0] = 1;
while(q.size())
{
int x = q.front().first;
int t = q.front().second;
q.pop();
v[x][t] = 0;
for(int i = head[x]; i; i = nxt[i])
{
int y = ver[i], z = edge[i];
if(d[y][t] > d[x][t] + z)
{
d[y][t] = d[x][t] + z;
if(!v[y][t])
q.push({y, t});
}
if(t + 1 <= k && d[y][t + 1] > d[x][t])
{
d[y][t + 1] = d[x][t];
if(!v[y][t + 1])
q.push({y, t + 1});
}
}
}
}
int main()
{
cin >> n >> m >> k >> s >> t;
for(int i = 1, x, y, z; i <= m; ++i)
{
cin >> x >> y >> z;
add(x, y, z);
add(y, x, z);
}
dij();
int ans = INT_MAX;
for(int i = 0; i <= k; ++i)
{
ans = min(ans, d[t][i]);
}
cout << ans << endl;
}