[BZOJ2763][JLOI2011]飞行路线
sol
很显然设\(f_{i,j}\)表示在\(i\)号点已经使用了\(j\)次免费的最小费用。
转移就是两种,使用免费或者是不使用。
相当于就是\(nk\)个点的最短路。
\(Dijkstra\)即可。
code
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#define pii pair<int,int>
#define mk make_pair
using namespace std;
int gi()
{
int x=0,w=1;char ch=getchar();
while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if (ch=='-') w=0,ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
const int N = 2e5+5;
int n,m,K,S,T,to[N],nxt[N],ww[N],head[N],cnt,dis[N],vis[N],ans=2e9;
priority_queue<pii,vector<pii>,greater<pii> >Q;
void link(int u,int v,int w)
{
to[++cnt]=v;nxt[cnt]=head[u];ww[cnt]=w;
head[u]=cnt;
}
void dijkstra()
{
memset(dis,63,sizeof(dis));
dis[S]=0;Q.push(mk(0,S));
while (!Q.empty())
{
int x=Q.top().second;Q.pop();
if (vis[x]) continue;vis[x]=1;
int u=x%n,t=x/n;
for (int e=head[u];e;e=nxt[e])
{
int v=to[e];
if (dis[v+t*n]>dis[x]+ww[e])
dis[v+t*n]=dis[x]+ww[e],Q.push(mk(dis[v+t*n],v+t*n));
if (dis[v+(t+1)*n]>dis[x]&&t<K)
dis[v+(t+1)*n]=dis[x],Q.push(mk(dis[v+(t+1)*n],v+(t+1)*n));
}
}
}
int main()
{
n=gi();m=gi();K=gi();S=gi();T=gi();
for (int i=1;i<=m;++i)
{
int u=gi(),v=gi(),w=gi();
link(u,v,w);link(v,u,w);
}
dijkstra();
for (int i=0;i<=K;++i)
ans=min(ans,dis[T+i*n]);
printf("%d\n",ans);return 0;
}