博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
分层图最短路【bzoj2763】: [JLOI2011]飞行路线
阅读量:5329 次
发布时间:2019-06-14

本文共 2691 字,大约阅读时间需要 8 分钟。

bzoj2763: [JLOI2011]飞行路线

Description

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

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

分层图最短路。

一直感觉这东西云里雾里的,做完这道题才发现其实也就那样。

有一点DP的思想,其实还是将状态全部枚举全就可以了。

这道题除了到达哪一个点这个状态之外,还会有用了多少次免费机会的这个状态。\(k\leq10\),看到这个我就放心了(想不出了k大一点这道题要怎么做。。。)

直接设状态为:\(dis[i][j]\)表示到达i这个点y用了j次机会的最短路。

那么我们用类似背包的思想去处理第二维状态。

也就是说我们到达每一个点,都会有两种状态:

一种是当前u到v的这条边我们不用免费条件,可以得到式子:

\[ dis(v)(ks)=min(dis(v)(ks),dis(u)(ks)+edge(i).dis) \]
那么相应地,就会有用掉免费条件的情况:
\[ dis(v)(ks+1)=min(dis(v)(ks+1),dis(u)(ks)) \]
再跑最短路的时候,到达每一个点都用着两种情况更新即可。

另外,bzoj数据不卡SPFA,洛谷的数据卡SPFA,实测。

#include
#include
#include
#include
using namespace std;const int wx=50017;inline char get_char(){ static char buf[1000001],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;}#define short long longinline short read(){ short num=0; char c; while(!isdigit(c=get_char())); for(num=c-48;isdigit(c=get_char());num=((num+(num<<2))<<1)+c-48); return num;}int n,m,k,s,t,num;int head[wx],vis[wx][11],dis[wx][11];struct e{ int nxt,to,dis;}edge[wx*2];void add(int from,int to,int dis){ edge[++num].nxt=head[from]; edge[num].to=to; edge[num].dis=dis; head[from]=num;}struct node{ int u,pos,d; friend bool operator < (const node & a,const node & b){ return a.d>b.d; }};priority_queue
q;void Dij(){ memset(dis,0x3f,sizeof dis); dis[s][0]=0;q.push((node){s,0,0}); while(q.size()){ int u=q.top().u;int ks=q.top().pos; q.pop(); if(vis[u][ks])continue;vis[u][ks]=1; for(int i=head[u];i;i=edge[i].nxt){ int v=edge[i].to; if(dis[v][ks]>dis[u][ks]+edge[i].dis){ dis[v][ks]=dis[u][ks]+edge[i].dis; q.push((node){v,ks,dis[v][ks]}); } if(ks+1<=k){ if(dis[v][ks+1]>dis[u][ks]){ dis[v][ks+1]=dis[u][ks]; q.push((node){v,ks+1,dis[v][ks+1]}); } } } }}int main(){ n=read();m=read();k=read();s=read();t=read();s++;t++; for(int i=1;i<=m;i++){ int x,y,z; x=read();y=read();z=read(); x++;y++; add(x,y,z);add(y,x,z); } Dij(); printf("%d\n",dis[t][k]); return 0;}

转载于:https://www.cnblogs.com/wangxiaodai/p/9759489.html

你可能感兴趣的文章
京东静态网页练习记录
查看>>
使用DBCP连接池对连接进行管理
查看>>
【洛谷】【堆+模拟】P2278 操作系统
查看>>
hdu3307 欧拉函数
查看>>
Spring Bean InitializingBean和DisposableBean实例
查看>>
Solr4.8.0源码分析(5)之查询流程分析总述
查看>>
[Windows Server]安装系统显示“缺少计算机所需的介质驱动程序”解决方案
查看>>
[容斥][dp][快速幂] Jzoj P5862 孤独
查看>>
Lucene 学习之二:数值类型的索引和范围查询分析
查看>>
软件开发工作模型
查看>>
Java基础之字符串匹配大全
查看>>
面向对象
查看>>
lintcode83- Single Number II- midium
查看>>
移动端 响应式、自适应、适配 实现方法分析(和其他基础知识拓展)
查看>>
selenium-窗口切换
查看>>
使用vue的v-model自定义 checkbox组件
查看>>
[工具] Sublime Text 使用指南
查看>>
Hangfire在ASP.NET CORE中的简单实现方法
查看>>
Algorithm——何为算法?
查看>>
Web服务器的原理
查看>>