洛谷P4568 飞行路线

题目描述

\(Alice\)\(Bob\)现在要乘飞机旅行,他们选择了一家相对便宜的航空公司。该航空公司一共在\(n\)个城市设有业务,设这些城市分别标记为\(0\)\(n−1\),一共有\(m\)种航线,每种航线连接两个城市,并且航线有一定的价格。

\(Alice\)\(Bob\)现在要从一个城市沿着航线到达另一个城市,途中可以进行转机。航空公司对他们这次旅行也推出优惠,他们可以免费在最多\(k\)种航线上搭乘飞机。那么\(Alice\)\(Bob\)这次出行最少花费多少?

输入输出格式

输入格式:

数据的第一行有三个整数,\(n,m,k\),分别表示城市数,航线数和免费乘坐次数。
第二行有两个整数,\(s,t\),分别表示他们出行的起点城市编号和终点城市编号。
接下来有\(m\)行,每行三个整数,\(a,b,c\),表示存在一种航线,能从城市\(a\)到达城市\(b\),或从城市\(b\)到达城市\(a\),价格为\(c\)

输出格式:

只有一行,包含一个整数,为最少花费。

输入输出样例

输入样例#1:

5 6 1
0 4
0 1 5
1 2 5
2 3 5
3 4 5
2 3 3
0 2 100

输出样例#1:

8

说明

对于\(30\%\)的数据,\(2 \le n \le 50,1 \le m \le 300,k=0\);
对于\(50\%\)的数据,\(2 \le n \le 600,1 \le m \le 6000,0 \le k \le 1\);
对于\(100\%\)的数据,\(2 \le n \le 10000,1 \le m \le 50000,0 \le k \le 10\)

\(2018.12.10\) 增加一组 \(hack\) 数据

思路:一个明显的分层最短路问题,就是建立\(n\)层图,然后建原图的映射边,每个点与它连向的点的映射点距离为\(0\),之后跑\(dijkstra\),因为\(k\)次免费机会可以不用完,所以从\(1\)\(k\)取最大值就好了。

代码:

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#include<cctype>
#define maxn 5000001
using namespace std;
int n,m,k,head[maxn],num,dis[maxn],s,t;
inline int qread() {
  char c=getchar();int num=0,f=1;
  for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
  for(;isdigit(c);c=getchar()) num=num*10+c-'0';return num*f;
}
struct Edge {
  int v,w,nxt;
}e[maxn];
struct node {
  int x,y;
  bool operator < (const node &a) const {return y>a.y;}
};
inline void ct(int u, int v, int w) {
  e[++num].v=v;
  e[num].w=w;
  e[num].nxt=head[u];
  head[u]=num;
}
priority_queue<node>q;
inline void dijkstra() {
  memset(dis,0x3f,sizeof(dis));
  dis[s+n*k]=0;q.push((node){s+n*k,0});
  while(!q.empty()) {
  	int u=q.top().x,d=q.top().y;
  	q.pop();
  	if(d!=dis[u]) continue;
  	for(int i=head[u];i;i=e[i].nxt) {
  	  int v=e[i].v;
	  if(dis[v]>dis[u]+e[i].w) {
	  	dis[v]=dis[u]+e[i].w;
	  	q.push((node){v,dis[v]});
	  }	
	}
  }
}
int main() {
  n=qread(),m=qread(),k=qread(),s=qread(),t=qread();
  for(int i=1,u,v,w;i<=m;++i) {
  	u=qread(),v=qread(),w=qread();
  	for(int j=0;j<=k;++j) {
  	  ct(u+j*n,v+j*n,w);
	  ct(v+j*n,u+j*n,w);
	  if(j) {
	  	ct(u+j*n,v+(j-1)*n,0);
	  	ct(v+j*n,u+(j-1)*n,0);
	  }	
	}
  }
  dijkstra();
  int zrj=0x7fffffff;
  for(int i=0;i<=k;++i) zrj=min(zrj,dis[t+i*n]);
  printf("%d\n",zrj);
  return 0; 
}
posted @ 2018-12-17 22:18  King丨帝御威  阅读(233)  评论(0编辑  收藏  举报
/*
*/