题目传送门
分层图最短路,或者说是一个DP,f[i][j]表示用了i张免费券,到了j号点的最小花费,然后跑最短路
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; int n,m,k,s,t,tot,dis[15][10005],ans = 2100000000,head[10005]; bool vis[15][10005]; struct kkk { int v,next,to; }e[100005]; struct node { int level,id,dist; bool operator <(const node &a) const { return dist > a.dist; } }; priority_queue<node> q; 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; } inline node cc(int l,int r,int w) { node pp; pp.dist = w; pp.id = r; pp.level = l; return pp; } inline void dijkstra() { memset(dis,0x3f3f3f,sizeof(dis)); dis[0][s] = 0; q.push(cc(0,s,0)); while(!q.empty()) { int u = q.top().level; int o = q.top().id; q.pop(); if(vis[u][o]) continue; vis[u][o] = 1; for(int i = head[o];i; i = e[i].next) { int vv = e[i].v; int w = e[i].to; if(dis[u][o] + vv < dis[u][w]) { dis[u][w] = dis[u][o] + vv; q.push(cc(u,w,dis[u][w])); } if(dis[u+1][w] > dis[u][o] && u < k) { dis[u+1][w] = dis[u][o]; q.push(cc(u + 1,w,dis[u+1][w])); } } } } int main() { scanf("%d%d%d%d%d",&n,&m,&k,&s,&t); 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); } dijkstra(); for(int i = 0;i <= k; i++) ans = min(ans,dis[i][t]); printf("%d",ans); return 0; }