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.
思路:
记得当时老师讲过一个分层图的题目,讲到如果是在草丛中什么的进入下一层,emmmmmm(@_@)记不清楚那个题目了,但是分层图的思想感觉很像dp,为了追求最优解而寻找各种状态
分层图性质:层之间是拓扑有序的。这也就意味着在层之间可以很容易实现递推等处理,为发现有效算法打下了良好的基础。
对于本题分析:
在第i层,我们可以继续按照原来的路线行走花费原来的权值,也可以用一次免费机会如果使用,则应将第i层的距离向i+1层转移,不加边权,相当于在这里用了一次免费机会;如果不使用,则应将第i层的距离向i+1层转移,加边权,免费机会不变
但是统计答案的时候有点迷,本以为需要不断比较取min来着。。。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
#define ri register int
typedef long long LL;
using namespace std;
const int sz = 100000;
const int inf = 1e8;
inline void rd(int &x){
x=0;bool f=0;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
if(f) x*=-1;
}
inline void we(int x){
if(x<0) putchar('-'),x*=-1;
if(x/10) we(x/10);
putchar(x%10+'0');
}
int dis[sz][15],fir[sz],nxt[sz<<1];
int n,m,k,s,e,tot;
bool use[sz][15];
struct ed{
int f,t,d;
}l[sz<<1];
void build(int f,int t,int d){
l[++tot]=(ed){f,t,d};
nxt[tot]=fir[f];
fir[f]=tot;
}
queue<int>q;
void spfa(int s)
{
dis[s][0]=0;
q.push(s),q.push(0);
use[s][0]=1;
while(!q.empty())
{
int u=q.front();q.pop();
int g=q.front();q.pop();
use[u][g]=0;
for(ri i=fir[u];~i;i=nxt[i])
{
int v=l[i].t;
if(dis[v][g]>dis[u][g]+l[i].d)
{
dis[v][g]=dis[u][g]+l[i].d;
if(!use[v][g])
{
q.push(v),q.push(g);
use[v][g]=1;
}
}
if(g<k)
{
if(dis[v][g+1]>dis[u][g])
{
dis[v][g+1]=dis[u][g];
if(!use[v][g+1])
{
q.push(v),q.push((g+1));
use[v][g+1]=1;
}
}
}
}
}
}
int main()
{
memset(fir,-1,sizeof(fir));
rd(n),rd(m),rd(k);
rd(s),rd(e);
for(ri i=1;i<=m;++i)
{
int x,y,z;
cin>>x>>y>>z;
build(x,y,z);
build(y,x,z);
}
for(ri i=0;i<n;++i)
for(ri j=0;j<=k;++j)
dis[i][j]=inf;
spfa(s);
we(dis[e][k]);
return 0;
}