Description
Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司。该航空公司一共在n个城市设有业务,设这些城市分别标记为0到n-1,一共有m种航线,每种航线连接两个城市,并且航线有一定的价格。Alice和Bob现在要从一个城市沿着航线到达另一个城市,途中可以进行转机。航空公司对他们这次旅行也推出优惠,他们可以免费在最多k种航线上搭乘飞机。那么Alice和Bob这次出行最少花费多少?
Input
数据的第一行有三个整数,n,m,k,分别表示城市数,航线数和免费乘坐次数。
第二行有两个整数,s,t,分别表示他们出行的起点城市编号和终点城市编号。(0<=s,t
Output
只有一行,包含一个整数,为最少花费。
Sample Input
5 6 1
0 4
0 1 5
1 2 5
2 3 5
3 4 5
2 3 3
0 2 100
Sample Output
8
HINT
对于30%的数据,2<=n<=50,1<=m<=300,k=0;
对于50%的数据,2<=n<=600,1<=m<=6000,0<=k<=1;
对于100%的数据,2<=n<=10000,1<=m<=50000,0<=k<=10.
分层图最短路。
将第i层的距离向i+1层转移,不加边权,相当于在这里用了一次免费机会。看起来是DP思想。
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int size=500010;
const int INF=233333333;
int head[size],nxt[size],dist[size][15],tot=0;
struct edge{
int t,d;
}l[size];
void build(int f,int t,int d)
{
l[++tot].t=t;
l[tot].d=d;
nxt[tot]=head[f];
head[f]=tot;
}
int n,m,k,s,t;
struct Heap{
int u,k,d;
Heap(int u,int k,int d)
{
this->u=u;
this->k=k;
this->d=d;
}
};
bool operator <(Heap a,Heap b)
{
return a.d>b.d;
}
priority_queue<Heap> q;
bool vis[size][15];
void dij(int s)
{
memset(dist,63,sizeof(dist));
dist[s][0]=0;
q.push(Heap(s,0,0));
while(q.size())
{
Heap f=q.top(); q.pop();
if(vis[f.u][f.k]) continue;
vis[f.u][f.k]=1;
for(int i=head[f.u];i;i=nxt[i])
{
int v=l[i].t;
if(dist[v][f.k]>dist[f.u][f.k]+l[i].d)
{
dist[v][f.k]=dist[f.u][f.k]+l[i].d;
q.push(Heap(v,f.k,dist[v][f.k]));
}
}
if(f.k<k)
{
for(int i=head[f.u];i;i=nxt[i])
{
int v=l[i].t;
if(dist[v][f.k+1]>dist[f.u][f.k])
{
dist[v][f.k+1]=dist[f.u][f.k];
q.push(Heap(v,f.k+1,dist[v][f.k+1]));
}
}
}
}
/* for(int i=1;i<=n;i++)
{
for(int j=0;j<=k;j++)
{
cout<<dist[i][j]<<" ";
}
puts("");
}*/
}
int main()
{
scanf("%d%d%d%d%d",&n,&m,&k,&s,&t);
s++,t++;
for(int i=1;i<=m;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
a++;b++;
build(a,b,c);
build(b,a,c);
}
dij(s);
int ans=INF;
for(int i=0;i<=k;i++) ans=min(ans,dist[t][i]);
printf("%d",ans);
return 0;
}