题目传送门
分层图最短路,和另一题几乎一样,唯一区别在于这道题是讲路径减半.
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int n,m,k,head[51],dis[51][51],tot,ans = 2099999999;
bool vis[51][51];
struct node {
int to,v,step;
bool operator <(const node &s) const {
return v > s.v;
}
};
priority_queue<node> q;
struct kkk {
int to,v,next;
}e[5001];
inline node dp(int cs,int d) {//此dp仅为一个名字
node p;
p.step = cs;
p.to = d;
p.v = dis[cs][d];
return p;
}
inline void spfa() {
memset(dis,0x3f,sizeof(dis));
dis[0][1] = 0;
q.push(dp(0,1));
while(!q.empty()) {
node w = q.top();
q.pop();
if(vis[w.step][w.to]) continue;
vis[0][1] = 1;
for(int i = head[w.to];i; i = e[i].next) {
int u = e[i].to;
if(dis[w.step][w.to] + e[i].v < dis[w.step][u]) {
dis[w.step][u] = dis[w.step][w.to] + e[i].v;
q.push(dp(w.step,u));
}
if(dis[w.step+1][u] > dis[w.step][w.to] + e[i].v / 2 && w.step < k) {
dis[w.step+1][u] = dis[w.step][w.to] + e[i].v / 2;
q.push(dp(w.step+1,u));
}
}
}
}
inline void add(int x,int y,int z) {
e[++tot].to = y;
e[tot].v = z;
e[tot].next = head[x];
head[x] = tot;
}
int main() {
scanf("%d%d%d",&n,&m,&k);
for(int i = 1;i <= m; i++) {
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
add(y,x,z);
}
spfa();
for(int i = 0;i <= k; i++)
ans = min(ans,dis[i][n]);
printf("%d",ans);
return 0;
}