题目【拆点】【分层图】【最短路】
思路
- 拆点: 将一个状态 拆为 k+1 个状态
- 原来dijkstra(dist, j)
- 现在拆成k+1个状态, 状态变为(dist, j, cnt) cnt为当前已免费使用的次数
代码(dijkstra + 拆点)
#include <bits/stdc++.h>
using namespace std;
const int N = 10010, M = 100010;
int h[N], e[M], w[M], ne[M], idx;
int n, m, k;
struct State{
int u, dist, cnt;
bool operator<(const State& t) const {
return dist > t.dist;
}
};
bool st[N][11];
int dist[N][11];//拆点
int S, T;
void add(int a,int b, int c)
{
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}
void dijkstra() {
priority_queue<State> pq;
pq.push({S, 0, 0});
memset(dist, 0x3f, sizeof dist);
dist[S][0] = 0;
while(pq.size()) {
auto t = pq.top(); pq.pop();
int u=t.u, cnt=t.cnt;
if(st[u][cnt]) continue;
st[u][cnt] = true;
for(int i=h[u]; ~i; i=ne[i]) {
int j = e[i];
//1 走w=0
if(cnt < k && dist[j][cnt+1] > dist[u][cnt]) {
dist[j][cnt+1] = dist[u][cnt];
pq.push({j,dist[j][cnt+1],cnt+1});
}
//2 走w=w
if(dist[j][cnt] > dist[u][cnt] + w[i]) {
dist[j][cnt] = dist[u][cnt] + w[i];
pq.push({j, dist[j][cnt], cnt});
}
}
}
}
int main()
{
memset(h, -1, sizeof h);
cin>>n>>m>>k;
cin>>S>>T;
while(m--) {
int a,b,c;
scanf("%d%d%d", &a, &b, &c);
add(a,b,c);
add(b,a,c);
}
dijkstra();
int res = INT_MAX;
for(int i=0; i<=k; ++i) res = min(res, dist[T][i]);
cout<<res;
return 0;
}