【[JLOI2011]飞行路线】
据说这是分层图最短路的板子题
但其实就是一个\(dij\)多带了一维状态
我们看到\(k\)很小所以显然我们可以设计一个这样的状态
\(d[v][k]\)表示从起点到点\(v\)免费走了\(k\)条路的最短路是多少
之后向下转移(即普通\(dij\)里的松弛)也很简单,就是有两种选泽,一种是这条路免费走,还有就是这条路不免费走
之后就很简单了
代码
#include<queue>
#include<cstdio>
#include<iostream>
#include<cstring>
#define re register
#define maxn 100001
#define to second.first
#define pre second.second
#define mp make_pair
#define inf 99999999999
#define int long long
using namespace std;
typedef pair<int,int> pi;
typedef pair<int,pi> pii;
priority_queue<pii,vector<pii>,greater<pii> > q;
struct eee
{
int v,nxt,w;
}e[maxn*10];
int d[maxn][21],n,m,head[maxn],num;
int f[maxn][21],t;
inline void add_edge(int x,int y,int z)
{
e[++num].v=y;
e[num].nxt=head[x];
e[num].w=z;
head[x]=num;
}
inline int read()
{
char c=getchar();
int x=0;
while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9')
x=(x<<3)+(x<<1)+c-48,c=getchar();
return x;
}
inline void dijkstra(int s)
{
for(re int i=0;i<n;i++)
for(re int j=0;j<=t;j++)
d[i][j]=inf;
d[s][0]=0;
q.push(mp(0,mp(s,0)));
while(!q.empty())
{
int k=q.top().to;
int pk=q.top().pre;
q.pop();
if(f[k][pk]) continue;
f[k][pk]=1;
for(re int i=head[k];i;i=e[i].nxt)
{
if(d[e[i].v][pk]>d[k][pk]+e[i].w)
{
d[e[i].v][pk]=d[k][pk]+e[i].w;
q.push(mp(d[e[i].v][pk],mp(e[i].v,pk)));
}
if(pk+1<=t&&d[e[i].v][pk+1]>d[k][pk])
{
d[e[i].v][pk+1]=d[k][pk];
q.push(mp(d[e[i].v][pk+1],mp(e[i].v,pk+1)));
}
}
}
}
signed main()
{
n=read();
m=read();
t=read();
int x,y,z;
int ss=read(),tt=read();
for(re int i=1;i<=m;i++)
{
x=read();
y=read();
z=read();
add_edge(x,y,z);
add_edge(y,x,z);
}
dijkstra(ss);
int ans=inf;
for(re int i=0;i<=t;i++)
ans=min(ans,d[tt][i]);
printf("%d\n",ans);
return 0;
}