题干:

Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司。该航空公司一共在n个城市设有业务,设这些城市分别标记为0到n-1,一共有m种航线,每种航线连接两个城市,并且航线有一定的价格。Alice和Bob现在要从一个城市沿着航线到达另一个城市,途中可以进行转机。航空公司对他们这次旅行也推出优惠,他们可以免费在最多k种航线上搭乘飞机。那么Alice和Bob这次出行最少花费多少?

Input

数据的第一行有三个整数,n,m,k,分别表示城市数,航线数和免费乘坐次数。

第二行有两个整数,s,t,分别表示他们出行的起点城市编号和终点城市编号。(0<=s,t<n)

接下来有m行,每行三个整数,a,b,c,表示存在一种航线,能从城市a到达城市b,或从城市b到达城市a,价格为c。(0<=a,b<n,a与b不相等,0<=c<=1000)

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.

解题报告:

注意一下数据范围,k=10,所以你需要乘以11,,,这题控制不好数据范围很容易就RE了、、、

AC代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN = 10000 + 5;
const int MAXM = 50000 + 5;
struct edge {int to, ne;int w;
} e[MAXM*4*11];
struct node {int u, c;node() {}node(int u, int c) : u(u), c(c) {}bool operator < (const node &a) const {return c > a.c;}
};
int head[MAXN*11], tot;
int dis[MAXN*11];
bool vis[MAXN*11];
int n, m, k;
int st,ed;
void add(int u, int v, int w) {e[++tot].to = v;e[tot].ne = head[u];e[tot].w = w;head[u] = tot;
}void Dijkstra(int st) {memset(dis, INF, sizeof dis);dis[st] = 0;priority_queue<node> pq;pq.push(node(st, 0));while(!pq.empty()) {node cur = pq.top(); pq.pop();if(vis[cur.u]) continue;vis[cur.u] = 1;for(int i=head[cur.u]; i!=-1; i=e[i].ne) {int v = e[i].to;if(dis[v] > cur.c+e[i].w) {dis[v] = cur.c+e[i].w;pq.push(node(v,dis[v]));}}}
}
int main()
{memset(head, -1, sizeof head);tot = 0;scanf("%d%d%d",&n,&m,&k);cin>>st>>ed;for(int i=1; i<=m; i++) {int u, v, w;scanf("%d%d%d",&u,&v,&w);for(int j = 0; j<=k; j++) {add(u+j*n,v+j*n,w);add(v+j*n,u+j*n,w);}for(int j = 0; j<k; j++) {add(u+j*n,v+(j+1)*n,0);add(v+j*n,u+(j+1)*n,0);}}Dijkstra(st);int ans = INF;for(int j = 0; j<=k; j++) {//不用~用k次,一共k+1个图 ans = min(ans,dis[j*n+ed]); }printf("%d\n",ans);return 0 ;
}

建立分层图的代码:

for(int i=1; i<=m; ++i) {scanf("%d%d%d",&a,&b,&c);for(int j=0; j<=k; ++j) {add(a+j*n,b+j*n,c);add(b+j*n,a+j*n,c);if(j<k) {add(a+j*n,b+(j+1)*n,0);add(b+j*n,a+(j+1)*n,0);}}
}

我们有k次免费坐飞机的机会,那么就有k+1个图 
我们只要保证我们每一次创建的图满足i*n+a(当前位置的标号)。

20190508更新:最短路dp的做法。

还WA了一发,,因为写着写着就忘了是双向边了。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define F first
#define S second
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
typedef pair<int,int> PII;
const int MAX = 2e5 + 5;
const int INF = 0x3f3f3f3f;
int dis[10005][12];
bool vis[10005][12];
int head[MAX],tot;
int n,m,k,st,ed;
struct Edge {int to,ne,w;
} e[MAX];
void add(int u,int v,int w) {e[++tot].to = v;e[tot].w=w;e[tot].ne=head[u];head[u] = tot;
}
struct Point {int pos,ci,c;Point(int pos=0,int ci=0,int c=0):pos(pos),ci(ci),c(c){}bool operator<(const Point b)const {return c > b.c;}
};
void Dijkstra() {priority_queue<Point> pq;for(int i = 1; i<=n; i++) {for(int j = 0; j<=k; j++) dis[i][j]=INF,vis[i][j]=0;}dis[st][0]=0;pq.push(Point(st,0,0));while(pq.size()) {Point cur = pq.top();pq.pop();if(cur.pos == ed) break;if(vis[cur.pos][cur.ci]) continue;vis[cur.pos][cur.ci] = 1;for(int i = head[cur.pos]; ~i; i = e[i].ne) {int v = e[i].to;if(vis[v][cur.ci] == 0) {if(dis[v][cur.ci] > dis[cur.pos][cur.ci] + e[i].w) {dis[v][cur.ci] = dis[cur.pos][cur.ci] + e[i].w;pq.push(Point(v,cur.ci,dis[v][cur.ci]));}}int tmpci = cur.ci+1;if(tmpci > k) continue;if(vis[v][tmpci] == 0) {if(dis[v][tmpci] > dis[cur.pos][cur.ci]) {dis[v][tmpci] = dis[cur.pos][cur.ci];pq.push(Point(v,tmpci,dis[v][tmpci]));}}}               }
}
int main()
{cin>>n>>m>>k;cin>>st>>ed;st++,ed++;for(int i = 1; i<=n+1; i++) head[i] = -1;for(int a,b,c,i = 1; i<=m; i++) {scanf("%d%d%d",&a,&b,&c);a++,b++;add(a,b,c);add(b,a,c);}Dijkstra();int ans = INF;for(int i = 0; i<=k; i++) {ans = min(ans,dis[ed][i]);}printf("%d\n",ans);return 0 ;
}
//21:20 - 21:39

【HYSBZ - 2763 】飞行路线 (分层图最短路,最短路dp)相关推荐

  1. 洛谷 - P4568 [JLOI2011]飞行路线(分层图最短路)

    题目链接:点击查看 题目大意:给出一张图,每条边都有权值,现在要求从点st到达点ed,沿途中可以让k条边的边权免费,现在求最短路 题目分析:分层图经典模板问题,直接套板子就行了,最后记得对于数组d的每 ...

  2. bzoj 2763 [JLOI2011]飞行路线——分层图

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2763 分层图两种方法的练习. 1.把图分成k+1层,本层去上面一层的边免费.但空间时间都不算 ...

  3. 图论之分层图最短路总结 与经典例题

    一.分层图 分层图只是建图时有区别,但跑最短路板子都是一样的,正所谓图论最难的就是建图,只要有合适的建图方法,那么问题就很简单了. 分层图是指有很多个平行的图,各个平行的图之间有特殊的连接边. 如何更 ...

  4. 图论 ---- E. Minimum Path(分层图最短路 用分层图对边权操作进行选择)

    题目链接 题目大意: 两点间最短路的定义变成:所有的边之和−max+min所有的边之和-max+min所有的边之和−max+min 解题思路: 这里很明显就是变成了最短路的时时候就是把路径上边权最小值 ...

  5. BZOJ2662[BeiJing wc2012]冻结——分层图最短路

    题目描述 "我要成为魔法少女!"      "那么,以灵魂为代价,你希望得到什么?"  "我要将有关魔法和奇迹的一切,封印于卡片之中„„"  ...

  6. CodeForces - 1486E Paired Payment(分层图最短路)

    题目链接:点击查看 题目大意:给出一个 nnn 个点 mmm 条边组成的带权无向图,规定每次只能走两条边,假设走的两条边为 a−>b−>ca->b->ca−>b−> ...

  7. 洛谷 - P4009 汽车加油行驶问题(分层图最短路/最小费用最大流)

    题目链接:点击查看 题目大意:给出一个n*n的矩阵表示道路,途中有一些加油站,现在要从点(1,1)到达点(n,n),问最小花费,其中的一些规则如下: 汽车只能沿着网格边行驶,装满油后可以行驶K条边,出 ...

  8. POJ - 3662 Telephone Lines(分层图最短路)

    题目链接:点击查看 题目大意:在郊区有N座通信基站,P条双向电缆,第i条电缆连接基站Ai和Bi.特别的,1号基站是通信公司的总站,N号基站位于一座农场中.现在,农场主希望对通信线路进行升级,其中升级第 ...

  9. 洛谷 P4011 孤岛营救问题【最短路+分层图】

    题外话:昨夜脑子昏沉,今早一调试就过了...错误有:我忘记还有墙直接穿墙过...memset初始化INF用错了数...然后手残敲错一个状态一直过不了样例...要是这状态去比赛我简直完了......or ...

最新文章

  1. Kotlin 函数的问题
  2. ubuntu18.04利用fdisk找到磁盘空闲区,新建分区,挂载
  3. [AT2567] [arc074_c] RGB Sequence
  4. VSCode摸鱼插件 — FreeWindow
  5. 希尔排序是一种稳定的排序算法_十大经典排序算法——希尔排序
  6. Dapper的语法应用
  7. python自带网页解析器_python 之网页解析器
  8. 回车键提交与不提交表单的解决方法
  9. xcode4.1自带SVN配置
  10. swig c java gemt,SWIG C函数指针和JAVA
  11. python撤销_python 取消转义字符作用
  12. 一款好用的日报管理系统“拍了拍”你,手把手教你如何写日报
  13. OCR条形码控件字体支持多种格式的OCR字体
  14. 怎么利用电脑摄像头和上传图片读取扫描二维码内容
  15. 1.14阅读论文:A Composite Failure Precursor for Condition Monitoring...Shuai Zhao等
  16. javaweb qq空间(博客)项目超详细开发套路原理分析
  17. 美林投资时钟策略如何运用?
  18. spa项目开发之vue+elementUi实现tab页
  19. 在iPhone上使用3D Touch
  20. 数学有什么用处?看完后恍然大悟!

热门文章

  1. [Leetcode][第99题][JAVA][恢复二叉搜索树][中序遍历]
  2. jmap 文件解析_干货分享丨jvm系列:dump文件深度分析
  3. centos 源码安装mysql5.6_CentOS 7下源码安装MySQL 5.6
  4. pq分解法中b’怎么求_14.初中数学:二元一次方程组,加减消元法怎么解?视频有详细解题步骤...
  5. 如何写一个脚本语言_零基础小白如何学会写文案?文案写作技巧之一:如何写一个吸引读者的文案开头...
  6. linux fb应用例子,Linux下利用framebuffer画点的程序小例子
  7. UE4异步编程专题 - 多线程
  8. Linux 定时器设置
  9. 定制mini2440 wince启动界面
  10. 在PC上用模拟器搭建Windows Mobile仿真环境:Microsoft Device Emulator使用