题意:最短路模板题 + 可以有k次机会免费走某条边
分析:dist[i][j]表示出发点到i 使用j次机会的最短路。跑dij的流程基本和裸的dij一致。
每次松弛的时候可以选择使用/不使用一次机会。 分别更新对应的状态即可。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
const int maxn = 5e4+10;
const int mx = 40;
const int mod = 1e9+5;
const ll inf = 34359738370;
const int INF = 1e9+7;
//最短路模板 但是可以选k条路使之免费 求s->t最短路
struct
{
int to,next,w;
}e[maxn<<1];
int head[maxn],cnt=0;
void add(int v,int u,int w)
{
e[++cnt].to=u;
e[cnt].w=w;
e[cnt].next=head[v];
head[v]=cnt;
}
struct node
{
int d,k,v;
bool operator < (const node &x)const
{
return d > x.d;
}
}h;
int n,m,k;
int s,t;
bool vis[maxn][15];
int dist[maxn][15];//到i 使用了j次免费机会的最短路
priority_queue<node> q;
void dij()
{
dist[s][0]=0;
q.push({0,0,s});
while(q.size())
{
h=q.top(),q.pop();
if(vis[h.v][h.k]) continue;
vis[h.v][h.k]=1;
for(int i=head[h.v];i;i=e[i].next)
{
int to=e[i].to;
//使用一次机会 转移到dp[to][h.k+1]
if(!vis[to][h.k+1] && h.k<k && dist[to][h.k+1] > h.d)
{
dist[to][h.k+1] = h.d;
q.push({dist[to][h.k+1],h.k+1,to});
}
//不使用机会 转移到dp[to][h.k]
if(!vis[to][h.k] && dist[to][h.k] > h.d+e[i].w)
{
dist[to][h.k] = h.d+e[i].w;
q.push({dist[to][h.k],h.k,to});
}
}
}
int ans=dist[t][0];
for(int i=1;i<=k;i++) ans=min(ans,dist[t][i]);
printf("%d\n",ans);
}
void init()
{
fill(dist[0],dist[0]+maxn*15,INF);
}
int main()
{
init();
scanf("%d %d %d %d %d",&n,&m,&k,&s,&t);
s++,t++;
for(int i=1;i<=m;i++)
{
int u,v,w;
scanf("%d %d %d",&u,&v,&w);
add(u+1,v+1,w);
add(v+1,u+1,w);
}
dij();
return 0;
}