题意:有n个城市,m条航线,每条航线都有一个权值,并且还多了k次免费航行的机会,求1~n的最短路;
做法:分层图+最短路;
1.分层图;因为多了k次免费航行,所以可以考虑建出k+1个图,然后跑一遍最短路;
2.最短路;既然能写分层图,那么最短路应该都会了吧,可以用 dijkstra 或 SPFA ;
附上代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#define pr pair<int ,int >
using namespace std;
const int N = 5e5+10;
const int inf = 0x3f3f3f3f;
inline int read(){
int ref=0,x=1;char ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) ref=ref*10+ch-'0',ch=getchar();
return ref*x;
}
int n,m,k,s,t;
struct edge{
int next,to,w;
}a[N<<4];
int head[N],cnt;
int dis[N<<4],vis[N<<4];
int ans=inf;
void add(int u,int v,int w){
a[++cnt]=(edge){head[u],v,w};
head[u]=cnt;
}
void dijkstra(int x){
memset(dis,inf,sizeof(dis));
priority_queue<pr ,vector<pr> ,greater<pr> > q;
q.push(make_pair(0,x));
dis[x]=0;
while(!q.empty()){
int temp=q.top().second;
q.pop();
if(vis[temp]) continue;
vis[temp]=1;
for(int i=head[temp];i;i=a[i].next){
int v=a[i].to;
if(dis[v]>dis[temp]+a[i].w){
dis[v]=dis[temp]+a[i].w;
q.push(make_pair(dis[v],v));
}
}
}
}
int main()
{
n=read(),m=read(),k=read();
s=read(),t=read();
for(int i=1;i<=m;++i){
int x,y,z;
x=read(),y=read(),z=read();
add(x,y,z),add(y,x,z);
for(int j=1;j<=k;++j){
add(x+j*n,y+j*n,z);
add(y+j*n,x+j*n,z);
add(x+(j-1)*n,y+j*n,0);
add(y+(j-1)*n,x+j*n,0);
}
}
dijkstra(s);
for(int i=0;i<=k;++i) ans=min(ans,dis[t+i*n]);
printf("%d",ans);
return 0;
}