【Usaco2014Open银组】双导航(gpsdual)
题目
【题目描述】
FJ 最近网购了一台小车。但是由于他的草率,在选择加装物品时偶然地点击了两次“Submit” ,结果最后他的小车装了两台GPS 导航系统!更糟的是,这两个系统对于FJ 要走的路线经常做出矛盾的判断。
FJ 居住地区的地图由N 个路口(2<=N <=10,000)和M 条有向边(1<=M<=50,000)组成。第i 条路连接路口Ai(1 <=Ai<=N)和Bi(1 <=Bi<=N)。对于同一对路口,可能有多条路连接它们;并且一条无向边会被表示成两条方向相反,连接路口相同的边。FJ 的房子位于第一路口,他的农场位于路口N。从他的房子出发,经过一系列有向边,是可以到达农场的。
两个GPS 系统基于如上面所描述的相同地图。然而,每条路它们存储的通过所需时间不相同。道路i 根据第一GPS 系统需要Pi 单位时间来通过,根据第二GPS 系统需要Qi 单位时间来通过(每个通过时间均是在1 到100,000 范围内的整数)。
FJ 想要从他的房子自驾车到农场。然而,当FJ 在一条某一个GPS 系统认为不属于最短路径内(从道路起始点X 到农场的最短路径)的道路(从路口X 到路口Y )上行驶时,这个GPS 系统会大声警告(如果FJ 选择的道路两个系统都不认可,那么两个系统都会警告FJ)。
请帮助FJ 找出,如果他恰当地选择他的路线,他能收到的警告最少是多少。
如果当FJ 沿一条道路走的时候两个GPS 都在警告,那么总警告数+2。
【输入】
第一行,整数N 和M。
接下来M 行,第i 行有四个整数Ai,Bi, Pi,Qi 描述第i 条道路。
【输出】
输出单独一行一个整数——FJ 选择从他家到达农场的最佳线路之后,路上收到的最小总警告数。
【样例输入】
5 7
3 4 7 1
1 3 2 20
1 4 17 18
4 5 25 3
1 2 10 1
3 5 4 14
2 4 6 5
【样例输出】
1
【样例解释】
输入详述:这里有5 个路口和7 条有向道路。第一条道路从路口3 到路口4 连接两个路口;第一GPS 认为这条路需要7 单位时间来通过,接着第二GPS 认为它只需1单位时间,诸如此类。
输出详述:如果FJ 按照路线1->2->4->5 走,那么第一GPS 会在1->2 这条路上发出警告(它认为1->3 这条路更好)。然而,对于路线剩下的2->4->5,两个GPS 都快乐地坐着FJ 的小车通过了,因为每个GPS 都以为这是2 到5 的最短路。
题解
这题主要讲了Farmer John把奶牛们打包送到肯德基后赚了一大笔钱,就网购小汽车。不料脑子瓦特了一下,订了两个GPS。店家黑心,没有告诉FJ这一消息,反而给了他两个版本不同的、声音响亮的GPS导航,这两个导航会在FJ不在走它们所认为的最短路时鸣叫,苦苦折磨着可怜的FJ。FJ就决定找一条去农场的最佳路径,使他被折磨的次数最少。
这题一眼扫过去,最短路算法!
没错,这题就是最短路,直觉没有坑害你。
于是一些人就立刻敲代码了,但是,怎么最短路呢?!
First,做这道题之前,你必须明白一件事——所谓的最短路是指到终点的最短路,当FJ从点 i 出发,走的边不是GPS认为的从点 i 出发去终点所要走的边时(即不在点 i 到终点的最短路上)就会发出警告。
所以要初始化从每一个点出发到终点要走那一条边(只会走一条)。
怎么弄呢?其实可以先跑一次SPFA,计算第一个GPS中每一个点到终点的距离(设第 i 个点的距离为\({dis1_{i}}\)),跑一次SPFA,计算第二个GPS中每一个点到终点的距离(设第 i 个点的距离为\({dis2_{i}}\))。根据SPFA算法的思路,可以推出,对于每一个导航,当点 i 和点 j 通过第 k 条边相连,点 j 到终点的距离被点 i 通过第 k 条边更新时,如果后来都没有任何点更新了点 i 和点 j 的最短路,那么\({dis_{i}+lenth_{k}=dis_{j}}\)(\(lenth_{k}\)表示第k条边的长度),由于对于每一个导航都是如此,我就用\(dis\)来代替\(dis1\)和\(dis2\)了。
如果点 i 离终点的最短距离被更新了,那么\(dis_{i}+lenth_{k}<dis_{j}\),如果点 j的被更新了,那么\(dis_{i}+lenth_{k}>dis_{j}\)。有人就要问了,如果i和j都被更新了怎么办?那样就必须再白一件事:如果点j到终点的最短路径中仍然是要经过点i的话,那么\(dis_{i}+lenth_{k}=dis_{j}\)(想一想,为什么);如果点j到终点的最短路径已经不用经过点i,那么\(dis_{i}+lenth_{k}<dis_{j}\)。
所以,再求出最短路径后,我们就可以枚举每一条边。设这条边的起点是u,终点是v,编号是i,当导航1在FJ经过这一条边时会发出警告,就一定会满足\(dis1_{i}+lenth_{k}>dis1_{j}\);当导航2在FJ经过这一条边时会发出警告,就一定会满足\(dis2_{i}+lenth_{k}>dis2_{j}\)
但是,这一切都搞定了,怎么求最少警告次数呢?
最短路!
我们可以视如果FJ经过一条边会被警告k次,那这一条边的权值就为k,这样弄完以后,再从起点出发跑一次SPFA就好了。
提示:由于本题要跑多次SPFA,建议建一个专门的函数来做SPFA。
代码
#include<cstdio>
#include<cstdlib>
using namespace std;
struct edge
{
int From,Lenth,To;
void swap()
{
int t=From;
From=To;
To=t;
}
}a[50010],b[50010],c[50010];
int n,m,dis[10010],date[51000],start[10010],end[10010];
bool exist[10010];
int cmp(const void *x,const void *y)
{
edge xx=*(edge*)x,yy=*(edge*)y;
if(xx.From!=yy.From) return xx.From-yy.From;
return xx.To-yy.To;
}
void spfa(int st)
{
int i,j,u,v,head=0,tail=1;
qsort(a+1,m,sizeof(edge),cmp);
for(i=1;i<=n;i++) dis[i]=2e9;
a[m+1].From=0;
for(i=1;i<=m+1;i++)
{
if(a[i].From!=a[i-1].From)
{
start[a[i].From]=i;
end[a[i-1].From]=i-1;
}
}
date[1]=st,dis[st]=0;
while(head<tail)
{
head++;
if(head==51000) head=1;
u=date[head];
exist[u]=0;
for(i=start[u];i<=end[u];i++)
{
v=a[i].To;
if(dis[u]+a[i].Lenth<dis[v])
{
dis[v]=dis[u]+a[i].Lenth;
if(!exist[v])
{
exist[v]=1;
tail++;
if(tail==51000) tail=1;
date[tail]=v;
}
}
}
}
}
int main()
{
freopen("gpsdual.in","r",stdin);
freopen("gpsdual.out","w",stdout);
int i,j,k,x,y,lena,lenb,t;
scanf("%d%d",&n,&m);
for(i=1;i<=m;i++)
{
scanf("%d%d%d%d",&x,&y,&lena,&lenb);
a[i]=(edge){y,lena,x};
b[i]=(edge){y,lenb,x};
c[i]=(edge){y,0,x};
}
qsort(c+1,m,sizeof(edge),cmp);
spfa(n);
for(i=1;i<=m;i++)//交换
{
if(dis[a[i].From]+a[i].Lenth>dis[a[i].To]) c[i].Lenth++;
a[i]=b[i];
}
spfa(n);
for(i=1;i<=m;i++)//交换
{
if(dis[a[i].From]+a[i].Lenth>dis[a[i].To]) c[i].Lenth++;
c[i].swap();
a[i]=c[i];
}
spfa(1);
printf("%d\n",dis[n]);
return 0;
}
【Usaco2014Open银组】双导航(gpsdual)的更多相关文章
- BZOJ USACO 银组 水题集锦
最近刷银组刷得好欢快,好像都是水题,在这里吧他们都记录一下吧(都是水题大家一定是道道都虐的把= =)几道比较神奇的题到时再列出来单独讲一下吧= =(其实我会说是BZOJ蹦了无聊再来写的么 = =) [ ...
- usaco 2010年3月银组题解
usaco银组解题报告 一.石子游戏如果把‘O’当作0,‘X’当做1,则N个洞的每一种状态都可以看做是一个N位二进制数.于是,这个问题就变成了求环绕的N位格雷码.幸运的是,这个结构很容易就能够用一个简 ...
- Bootstrap -- 下拉菜单、输入框组、导航菜单
Bootstrap -- 下拉菜单.输入框组.导航菜单 1. 下拉菜单 可以使用带有各种大小按钮的下拉菜单:.btn-lg..btn-sm 或 .btn-xs. 实现下拉菜单: <!DOCTYP ...
- Android典型界面设计(3)——访网易新闻实现双导航tab切换
一.问题描述 双导航tab切换(底部区块+区域内头部导航),实现方案底部区域使用FragmentTabHost+Fragment, 区域内头部导航使用ViewPager+Fragment,可在之前博客 ...
- Android典型界面设计(7) ——DrawerLayout+Fragement+ViewPager+PagerTabStrip实现双导航
一.问题描述 在Android典型界面设计(3)的我们实现了双导航效果,即外层底部导航和内部区域的头部导航,如网易新闻等很多应用采用了这种导航,但Google提供DrawerLayout可实现抽屉式导 ...
- Android典型界面设计-访网易新闻实现双导航tab切换
一.问题描述 双导航tab切换(底部区块+区域内头部导航),实现方案底部区域使用FragmentTabHost+Fragment, 区域内头部导航使用ViewPager+Fragment,可在之前博客 ...
- bootstrap学习笔记<十>(按钮组,导航)
1)按钮组.样式:class="btn-group" <div class="btn-group"> <button class=" ...
- bootstrap输入框组、导航和导航条
输入框组(input groups) 避免使用select 支持不好,使用输入框组 尺寸根据 input-group-lg input-group-sm来选择 <div class ...
- Android典型界面设计(8) ——ViewPager+PagerSlidingTabStrip实现双导航
一.问题描述 PagerSlidingTabStrip是android开源项目,指示器控件.官网地址:https://github.com/astuetz/PagerSlidingTabStrip 该 ...
随机推荐
- rabbitmq 的安装配置使用
前言: 对于消息队列中间件: #redis: 功能比较全,但是如果突然停止运行或断电会造成数据丢失 #RabbitMQ:功能比较齐全.稳定.便于安装,在生产环境来说是首选的 1.下载软件[下载较慢,请 ...
- JavaWeb_(Hibernate框架)Hibernate配置文件hibernate.cfg.xml
hibernate.cfg.xml配置文件——链接数据库 hibernate.cfg.xml一定要配置在/src文件目录下 --数据库驱动,url,用户名,密码 --方言org.hibernate.d ...
- linux修改ulimit参数
有如下三种修改方式: 1.在/etc/rc.local 中增加一行 ulimit -SHn 655352.在/etc/profile 中增加一行 ulimit -SHn 655353.在/etc/se ...
- Ranger使用solrCloud存储审计日志
Ranger使用solrCloud存储审计日志 标签(空格分隔): Ranger 1, Zookeeper 搭建 1,忽略.默认已经搭建好zk 集群. VECS17820:2181,VECS17821 ...
- Python代码整洁之道(一)
很多新手在开始学一门新的语言的时候,往往会忽视一些不应该忽视的细节,比如变量命名和函数命名以及注释等一些内容的规范性,久而久之养成了一种习惯.对此呢,我特意收集了一些适合所有学习 Python 的人, ...
- springboot @Configuration配置类里面使用@Value获取不到.yml配置文件属性的值
之前一个项目里面分为很多子工程的那种结构,要求让我改成一个项目的结构.我这边手动将代码合并之后出现下面的这种问题,然后尝试进行用各种方式解决 Error creating bean with name ...
- 石川es6课程---18、ES6 复习
石川es6课程---18.ES6 复习 一.总结 一句话总结: 无论在讲课和学习中,复习总结都是很重要 二.ES6 复习 变量 let const 声明方式 能否重复声明 作用域 类型 是否支持变量提 ...
- dnSpy PE format ( Portable Executable File Format)
Portable Executable File Format PE Format 微软官方的 What is a .PE file in the .NET framework? [closed] ...
- 转贴 使用正则表达式解析一般sql语句(C++)
https://blog.csdn.net/dreamgchuan/article/details/47715743 --END--2019年9月5日11点58分
- golang 性能剖析pprof
作为一个golang coder,使用golang编写代码是基本的要求. 能够写出代码,并能够熟悉程序执行过程中各方面的性能指标,则是更上一层楼. 如果在程序出现性能问题的时候,可以快速定位和解决问题 ...