Luogu P4568 【[JLOI2011]飞行路线】题解
分层图的模版题
什么是分层图
分层图--------可以理解为有多个平行的图
第i层表示用了i张免费卷后到达每个点的最短路
显然,可以在同层跑最短路,而低层可以到高层
这就满足了在不同层间无后效性的拓展
于是我们可以设状态
dis[i][j]//表示在第j层(用j张免费卷)到第i个点的最短路径
dis[i][j]=Min(Min{dis[k][j]+value[k][i]},Min{dis[k][j-1]})
//k为与i联通的点
献上我丑陋的代码:
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define ll long long
struct point{
ll d,id,dep;
bool operator <(const point &a)const{
return d>a.d;
}
};
priority_queue<point>q;
ll u[100005],v[100005],w[100005];
ll first[10005],next[100005];
ll tot=0;
inline void addedge(ll a,ll b,ll c){
tot++;u[tot]=a,v[tot]=b,w[tot]=c;
next[tot]=first[a];first[a]=tot;
}
ll dis[10005][15];
ll vis[10005][15];
ll n,m,k;
//管它卡不卡spfa,dij+heap常规操作
ll dijkstra(ll s,ll t){
memset(dis,0x3f,sizeof dis);
dis[s][0]=0;q.push({0,s,0});vis[s][0]=1;
while(!q.empty()){
point p=q.top();q.pop();
ll x=p.id,op=p.dep,d=p.d;
if(d!=dis[x][op])continue;
vis[x][op]=1;
for(int i=first[x];i;i=next[i]){
int y=v[i];
if(!vis[y][op]){
if(dis[y][op]>dis[x][op]+w[i]){
dis[y][op]=dis[x][op]+w[i];
q.push({dis[y][op],y,op});
}
}
if(op<k&&!vis[y][op+1]){
if(dis[y][op+1]>dis[x][op]){
dis[y][op+1]=dis[x][op];
q.push({dis[y][op+1],y,op+1});
}
}
}
}
return dis[t][k];
}
int main(){
scanf("%lld%lld%lld",&n,&m,&k);
ll s,t;scanf("%lld%lld",&s,&t);
for(ll i=1;i<=m;i++){
ll a,b,c;scanf("%lld%lld%lld",&a,&b,&c);
addedge(a,b,c);addedge(b,a,c);
}
printf("%lld",dijkstra(s,t));
return 0;
}