【习题·图论】[JLOI2011]飞行路线:拆点最短路

2023-10-13 13:18

本文主要是介绍【习题·图论】[JLOI2011]飞行路线:拆点最短路,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目描述

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

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

Solution

可以知道,这道题目一定是最短路;但是多了一个限制:有 k k k条路线可以免费。

此时,若以点为单位跑最短路显然不行。我们需要拆点,或者说是分层图:

其中 d ( u , f r e ) d(u,fre) d(u,fre)表示到节点 u u u,使用了 f r e fre fre次免费搭乘的最小话费。

就是这样的(盗个图):
分层图
那么如何在最短路里进行点与点之间的转移呢?

可以得到: d ( u , f r e ) + v a l → d ( v , f r e ) , 不 用 免 费 换 乘 d(u,fre)+val→d(v,fre),不用免费换乘 d(u,fre)+vald(v,fre),
d ( u , f r e ) → d ( v , f r e + 1 ) , 使 用 免 费 换 乘 . d(u,fre)→d(v,fre+1),使用免费换乘. d(u,fre)d(v,fre+1),使.

其中 u u u v v v相连,边权为 v a l val val。那么最后的答案 a n s = d ( e , i ) , i ∈ [ 0 , k ] . ans=d(e,i),i∈[0,k]. ans=d(e,i),i[0,k].

代码如下:

#include<bits/stdc++.h>
using namespace std;
#define Mp make_pair
struct edge{int pnt,val;
};
int n,m,k,S,T;
int d[20000][20];
int v[20000][20];
vector<edge>a[20000];
inline int read()
{int s=0;char c=getchar();while (c<'0' || c>'9') c=getchar();while (c>='0' && c<='9') s=s*10+c-48,c=getchar();return s;
} 
int main(void)
{int n=read(),m=read(),k=read();int S=read()+1,T=read()+1;for (int i=1;i<=m;++i){int x=read()+1,y=read()+1,v=read();a[x].push_back(edge{y,v});a[y].push_back(edge{x,v});}memset(d,30,sizeof(d));d[S][0]=0;priority_queue< pair<int,pair<int,int> > > q;q.push(Mp(0,Mp(S,0)));while (q.size()){int now=q.top().second.first;int fre=q.top().second.second;q.pop();if (v[now][fre]) continue;else v[now][fre]=1;for (int i=0;i<a[now].size();++i){int Next=a[now][i].pnt;int Val=a[now][i].val;if (d[now][fre]+Val<d[Next][fre]){d[Next][fre]=d[now][fre]+Val;q.push(Mp(-d[Next][fre],Mp(Next,fre)));}if (d[now][fre]<d[Next][fre+1] && fre<k){d[Next][fre+1]=d[now][fre];q.push(make_pair(-d[Next][fre+1],Mp(Next,fre+1)));}}}int ans=INT_MAX;for (int i=0;i<=k;++i) ans=min(ans,d[T][i]);printf("%d\n",ans);return 0;
} 

这篇关于【习题·图论】[JLOI2011]飞行路线:拆点最短路的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/203479

相关文章

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

【专题】2024飞行汽车技术全景报告合集PDF分享(附原数据表)

原文链接: https://tecdat.cn/?p=37628 6月16日,小鹏汇天旅航者X2在北京大兴国际机场临空经济区完成首飞,这也是小鹏汇天的产品在京津冀地区进行的首次飞行。小鹏汇天方面还表示,公司准备量产,并计划今年四季度开启预售小鹏汇天分体式飞行汽车,探索分体式飞行汽车城际通勤。阅读原文,获取专题报告合集全文,解锁文末271份飞行汽车相关行业研究报告。 据悉,业内人士对飞行汽车行业

poj 1511 Invitation Cards(spfa最短路)

题意是给你点与点之间的距离,求来回到点1的最短路中的边权和。 因为边很大,不能用原来的dijkstra什么的,所以用spfa来做。并且注意要用long long int 来存储。 稍微改了一下学长的模板。 stack stl 实现代码: #include<stdio.h>#include<stack>using namespace std;const int M

poj 3259 uva 558 Wormholes(bellman最短路负权回路判断)

poj 3259: 题意:John的农场里n块地,m条路连接两块地,w个虫洞,虫洞是一条单向路,不但会把你传送到目的地,而且时间会倒退Ts。 任务是求你会不会在从某块地出发后又回来,看到了离开之前的自己。 判断树中是否存在负权回路就ok了。 bellman代码: #include<stdio.h>const int MaxN = 501;//农场数const int

poj 1502 MPI Maelstrom(单源最短路dijkstra)

题目真是长得头疼,好多生词,给跪。 没啥好说的,英语大水逼。 借助字典尝试翻译了一下,水逼直译求不喷 Description: BIT他们的超级计算机最近交货了。(定语秀了一堆词汇那就省略吧再见) Valentine McKee的研究顾问Jack Swigert,要她来测试一下这个系统。 Valentine告诉Swigert:“因为阿波罗是一个分布式共享内存的机器,所以它的内存访问

poj 3159 (spfa差分约束最短路) poj 1201

poj 3159: 题意: 每次给出b比a多不多于c个糖果,求n最多比1多多少个糖果。 解析: 差分约束。 这个博客讲差分约束讲的比较好: http://www.cnblogs.com/void/archive/2011/08/26/2153928.html 套个spfa。 代码: #include <iostream>#include <cstdio>#i

hdu 3790 (单源最短路dijkstra)

题意: 每条边都有长度d 和花费p,给你起点s 终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。 解析: 考察对dijkstra的理解。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstrin

poj 3255 次短路(第k短路) A* + spfa 或 dijkstra

题意: 给一张无向图,求从1到n的次短路。 解析: A* + spfa 或者 dijkstra。 详解见上一题:http://blog.csdn.net/u013508213/article/details/46400189 本题,spfa中,stack超时,queue的效率最高,priority_queue次之。 代码: #include <iostream>#i

poj 2449 第k短路 A* + spfa

poj 2449: 题意: 给一张有向图,求第k短路。 解析: A* + spfa。 一下转自:http://blog.csdn.net/mbxc816/article/details/7197228 “描述一下怎样用启发式搜索来解决K短路。 首先我们知道A*的基础公式:f(x)=g(x)+h(x);对h(x)进行设计,根据定义h(x)为当前的x点到目标点t所需要的实际距

poj 3422 有流量限制的最小费用流 反用求最大 + 拆点

题意: 给一个n*n(50 * 50) 的数字迷宫,从左上点开始走,走到右下点。 每次只能往右移一格,或者往下移一格。 每个格子,第一次到达时可以获得格子对应的数字作为奖励,再次到达则没有奖励。 问走k次这个迷宫,最大能获得多少奖励。 解析: 拆点,拿样例来说明: 3 2 1 2 3 0 2 1 1 4 2 3*3的数字迷宫,走两次最大能获得多少奖励。 将每个点拆成两个