问题描述

洛谷(有翻译)


吐槽

一道坑题。


如何对待商务票

因为商务票只有一张,所以在\(k\)条边中只有一条边会被选中,很显然,最后这条边会被枚举。


如何选择使用商务票的边

假设我们正在枚举这条边,现在的边为\((u,v)\),边权为\(w\)。

那么现在的最小代价肯定为

\[min(dist_{(s,u)_{min}}+dist_{(v,e)_{min}}+w,dist_{(s,v)_{min}}+dist_{(u,e)_{min}}+w)
\]

其中\(s\)代表起点,\(e\)代表终点,\(dist_{(a,b)}\)代表\(a\)到\(b\)的距离。

从\(dist_{(a,b)_{min}}\)中,我们可以很清楚地感受到,需要跑最短路。

强烈推荐使用\(dijkstra\)+堆优化。

如果你不确定你的最短路模板是否正确,请移步


两次最短路

经过分析,我们知道要跑最短路,但是由于有两个点分别到\(s\)和\(e\)的最短距离,那么就需要以\(s\)和\(e\)分别为源,跑单源最短路径。

最短路中需要记录前驱。


总思路

先读入,注意多组测试数据。

再跑两遍最短路。

枚举\(k\)条边,对于每一条边\((u,v)\),用上面的公式和当前最优的\(ans\)比较并记录。

最后输出。(如果挂了先调这个)


细节

  • 每组测试数据的输出之间需要一个空行

  • 最后一组测试数据后不能有空行

  • 行末不能有多余的空格


彩蛋

点这里

可能有点卡


代码

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std; #define maxn 500
#define maxm 1000
struct node{
int dis,x;
bool operator <(const node &a)const
{
return dis>a.dis;
}
};
int h_j[maxn+7],n_j[maxm*2+7],h_s[maxn+7],n_s[maxm*2+7],u_j[maxm*2+7],v_j[maxm*2+7],w_j[maxm*2+7],tot_j,u_s[maxm*2+7],v_s[maxm*2+7],w_s[maxm*2+7],tot_s;
int s,e,n,m,k,x,y,z,p[maxn+7],dis1[maxn+7],dis2[maxn+7],qi1[maxn+7],qi2[maxn+7],ans=0x7fffffff,ansi,ansj;
bool used1[maxn+7],used2[maxn+7];
int u[maxm+7],v[maxm+7],w[maxm+7],stac[maxn+7],cas,xx,top;
void add_j()
{
u_j[++tot_j]=x,v_j[tot_j]=y,w_j[tot_j]=z;
n_j[tot_j]=h_j[x],h_j[x]=tot_j;
u_j[++tot_j]=y,v_j[tot_j]=x,w_j[tot_j]=z;
n_j[tot_j]=h_j[y],h_j[y]=tot_j;
}
void clear()
{
memset(h_j,0,sizeof(h_j));
memset(n_j,0,sizeof(n_j));
memset(used1,0,sizeof(used1));
memset(used2,0,sizeof(used2));
tot_j=0;
memset(qi1,0,sizeof(qi1));
memset(qi2,0,sizeof(qi2));
ans=0x7fffffff;
}
int mian()
{
while((~scanf("%d%d%d",&n,&s,&e))&&n&&s&&e)
{
if(cas++) printf(" ");
clear();
scanf("%d",&m);
for(register int i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&z);
add_j();
}
scanf("%d",&k);
for(register int i=1;i<=k;i++)
{
scanf("%d%d%d",&x,&y,&z);
u[i]=x,v[i]=y,w[i]=z;
}
for(register int i=1;i<=n;i++) dis1[i]=dis2[i]=0x3f3f3f3f;
priority_queue<node>q1;
dis1[s]=0;
q1.push((node){0,s});
while(!q1.empty())
{
int u=q1.top().x;
q1.pop();
if(used1[u]) continue;
used1[u]=1;
for(int i=h_j[u];i;i=n_j[i])
{
int aa=v_j[i],co=w_j[i];
if(dis1[aa]>dis1[u]+co)
{
dis1[aa]=dis1[u]+co;qi1[aa]=u;
q1.push((node){dis1[aa],aa});
}
}
}
priority_queue<node>q2;
dis2[e]=0;
q2.push((node){0,e});
while(!q2.empty())
{
int u=q2.top().x;
q2.pop();
if(used2[u]) continue;
used2[u]=1;
for(int i=h_j[u];i;i=n_j[i])
{
int aa=v_j[i],co=w_j[i];
if(dis2[aa]>dis2[u]+co)
{
dis2[aa]=dis2[u]+co;qi2[aa]=u;
q2.push((node){dis2[aa],aa});
}
}
}
for(register int i=1;i<=k;i++)
{
if(dis1[u[i]]+dis2[v[i]]+w[i]<=ans)
{
ans=dis1[u[i]]+dis2[v[i]]+w[i];
ansi=u[i];
ansj=v[i];
}
if(dis1[v[i]]+dis2[u[i]]+w[i]<=ans)
{
ans=dis1[v[i]]+dis2[u[i]]+w[i];
ansi=v[i];
ansj=u[i];
}
}
xx=ansi;
top=0;
if(s==e)
{
printf("%d\nTicket Not Used\n0\n",s);
continue;
}
if(ans<=dis1[e])
{
while(xx!=s&&xx)
{
stac[++top]=xx;
xx=qi1[xx];
}
printf("%d ",s);
while(top)
{
printf("%d ",stac[top--]);
}
xx=ansj;
while(xx!=e&&xx)
{
stac[++top]=xx;
xx=qi2[xx];
}
int fuck=1;
while(fuck<=top)
{
printf("%d ",stac[fuck++]);
}
printf("%d\n",e);
printf("%d\n%d\n",ansi,ans);
}
else
{
int xx=qi1[e];
while(xx!=s&&xx)
{
stac[++top]=xx;
xx=qi1[xx];
}
printf("%d ",s);
while(top)
{
printf("%d ",stac[top--]);
}
printf("%d\nTicke Not Used\n%d\n",e,dis1[e]);
}
}
}

UVA11374 Airport Express 正反两次最短路的更多相关文章

  1. UVA-11374 Airport Express (dijkstra+枚举)

    题目大意:n个点,m条无向边,边权值为正,有k条特殊无向边,起止点和权值已知,求从起点到终点的边权值最小的路径,特殊边最多只能走一条. 题目分析:用两次dijkstra求出起点到任何一个点的最小权值, ...

  2. Uva11374 Airport Express

    最短路问题. 从起点和终点开始各跑一次dijkstra,可以得到起点.终点到任意点的距离.枚举使用的商业线路,找最优解. 破题卡输出,记录前驱和输出什么的仿佛比算法本身还麻烦. /*by Silver ...

  3. poj 3268 Silver Cow Party(最短路,正反两次,这个模版好)

    题目 Dijkstra,正反两次最短路,求两次和最大的. #define _CRT_SECURE_NO_WARNINGS //这是找出最短路加最短路中最长的来回程 //也就是正反两次最短路相加找最大的 ...

  4. UVA - 11374 - Airport Express(堆优化Dijkstra)

    Problem    UVA - 11374 - Airport Express Time Limit: 1000 mSec Problem Description In a small city c ...

  5. UVA - 11374 Airport Express (Dijkstra模板+枚举)

    Description Problem D: Airport Express In a small city called Iokh, a train service, Airport-Express ...

  6. BNUOJ 19792 Airport Express

    Airport Express Time Limit: 1000ms Memory Limit: 131072KB This problem will be judged on UVA. Origin ...

  7. UVA 11374 Airport Express SPFA||dijkstra

    http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...

  8. 【uva11374】Airport Express 最短路

    题意: 在Iokh市中,机场快线是市民从市内去机场的首选交通工具.机场快线分为经济线和商业线两种,线路,速度和价钱都不同.你有一张商业线车票,可以坐一站商业线,而其他时候只能乘坐经济线.假设换乘时间忽 ...

  9. UVA 11374 Airport Express(最短路)

    最短路. 把题目抽象一下:已知一张图,边上的权值表示长度.现在又有一些边,只能从其中选一条加入原图,使起点->终点的距离最小. 当加上一条边a->b,如果这条边更新了最短路,那么起点st- ...

随机推荐

  1. Day13- Python基础13 生产者与消费者模型,进程

    本节内容: 1:生产者与消费者 2:进程调用两种 3:进程Process的方法 4:进程间的通信1 queue 队列 5:进程间的通信2 Pipe 管道 6:进程间的数据共享 Managers 7:进 ...

  2. 201871010116-祁英红《面向对象程序设计(java)》第十二周学习总结

    博文正文开头格式:(2分) 项目 内容 <面向对象程序设计(java)> https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://ww ...

  3. cmd如何跨盘cd切换路径

    cmd跨盘cd要加参数 /d ,难怪,我还以为电脑有问题呢~

  4. AcWing 800. 数组元素的目标和

    网址 https://www.acwing.com/solution/AcWing/content/2064/ 题目描述给定两个升序排序的有序数组A和B,以及一个目标值x,请你求出满足A[i] + B ...

  5. AcWing 33. 链表中倒数第k个节点

    习题地址 https://www.acwing.com/solution/acwing/content/2997/ 题目描述输入一个链表,输出该链表中倒数第k个结点. 注意: k >= 0;如果 ...

  6. appium应用切换以及toast弹出框处理

    一.应用切换 应用切换的方法很简单,直接调用driver.start_activity()方法,传入app_package和app_activity参数,示例代码如下: from appium imp ...

  7. SPU和SKU介绍及区别

    一.spu概念 SPU = Standard Product Unit (标准化产品单元) SPU是商品信息聚合的最小单位,是一组可复用.易检索的标准化信息的集合,该集合描述了一个产品的特性.通俗点讲 ...

  8. 黄聪:不使用 webpack,vuejs 异步加载模板

    webpack 打包不会玩,整了这么个小玩具 一段 vue 绑定代码,关键点在 gmallComponent 1.异步加载外部 vue 文件(非 .vue) 2.按一定规则拆分 template.sc ...

  9. 基础面试,为什么面试官总喜欢问String?

    关于 Java String,这是面试的基础,但是还有很多童鞋不能说清楚,所以本文将简单而又透彻的说明一下那个让你迷惑的 String 在 Java 中,我们有两种方式创建一个字符串 String x ...

  10. Requests库主要方法解析以及Requests库入门需要掌握的框架

    Requests库主要方法解析以及Requests库入门 1.requests.request(method,url,**kwargs) **kwargs:控制访问的参数,均为可选项 params:字 ...