NOIP模拟赛(by hzwer) T3 小奇回地球

【题目背景】

  开学了,小奇在回地球的路上,遇到了一个棘手的问题。

【问题描述】

  简单来说,它要从标号为 1 的星球到标号为 n 的星球,某一些星球之间有航线。 由于超时空隧道的存在,从一个星球到另一个星球时间可能会倒流,而且,从星 球 a 到 b 耗费的时间和星球 b 到 a 耗费的时间不一定相同。宇宙法规定:“禁止在出发时间前到达目的地”。每艘飞船上都有速度调节装置,可以调节飞行的时间。其功能可以使得整次航程中所有两星球间的飞行时间增加或减少相同的整数值。你的任务是帮助它调整速度调节器,找出一条最短时间到达目的地的路径。

【输入格式】

  输入文件包含多组数据,第 1 个数为 T,表示数据组数。对于每组数据,输入第 1 行为两个正整数 n,m,为星球的个数和星球间的路线数。接下来 m 行,每行三个整数 i,j 和 t,表示由星球 i 到星球 j 飞行的时间为 t。由 i 到 j 最多只会有一条飞行线路。

【输出格式】

  输出文件共 T 行,每组数据输出一行。

  如果可以通过调节速度调节器完成任务,则输出一个非负整数,表示由星球1到星球 n 的最短时间。(注意最短时间要大于或者等于 0)。如果不能由星球 1 到达星球 n,则输出-1。

【样例输入】

  1

  4 5

  1 2 1

  1 3 1

  2 3 -3

  3 1 1

  3 4 1

【样例输出】

  2

【样例解释】

  把速度控制器的值设为 1,相当于每个时间值加 1,得到的最短路径为 1→2→3→4。所需时间为 2+(-2)+2=2。

【数据范围】

  1,2 号测试点,保证所有星球出度不超过1

  3,4 号测试点,n<=10

  5,6 号测试点,-100<=t<=100

  对于 100%的数据 T<=10,n<=100,m<=n*(n-1),-100000<=t<=100000

  数据随机和构造结合生成

【解析】

  将此题简化后可得如下模型:给定一张有向图(有负边权),可以使每一条边加上或减去一个值t,使从1到n的最短路径最小且非负。

  经过分析可以知道,若给每一条边加上一个值t0后,1到n的最短路为负,那么对于任意t<t0都有最短路径仍为负。由此可以想到二分答案。t的值域为-100000到100000,那么二分的左右边界就定好了。然后每次都用SPFA检验最短路径是否大于等于0,然后......死循环了。

  为什么呢?假设有t1<0,那么图中就有几率出现负权环,那么就没有最短路。所以要在SPFA中加入判断负权环的内容。但即使这样仍会超时。那么我们继续思考怎么优化。显然,如果一个点与1或n不连通,那么它对答案是没有贡献的。我们先从1出发遍历整张图,把无法到达的点删去。然后再从1能够到达的点出发,如果该点不能到达n,也从集合中删去。在“砍图”之后,虽然时间已经优化了,但仍然不够。题目中有一句话是这么说的:

数据随机和构造结合生成

  那是不是会卡SPFA呢?所以,一个神奇的操作就出来了:深度优先搜索版SPFA。用DFS-SPFA去判断负权环即可。

【代码】

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define N 102
#define M 200002
using namespace std;int head[N],ver[M],nxt[M],edge[M],c;
int t,n,m,i,cnt[N],dis[N];
bool e[N],vis[N],in[N];
queue<int> q;
int read()
{char c=getchar();int w=0,f=1;while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}while(c<='9'&&c>='0'){w=w*10+c-'0';c=getchar();}return w*f;
}
void insert(int x,int y,int z)
{c++;ver[c]=y;edge[c]=z;nxt[c]=head[x];head[x]=c;
}
bool dfs_SPFA(int x,int s)
{vis[x]=1;for(int i=head[x];i;i=nxt[i]){int y=ver[i];if(dis[y]>dis[x]+edge[i]+s&&e[y]){if(vis[y]) return 1;dis[y]=dis[x]+edge[i]+s;if(dfs_SPFA(y,s)) return 1;}}vis[x]=0;return 0;
}
void SPFA(int s)
{memset(dis,0x3f,sizeof(dis));memset(in,0,sizeof(in));q.push(1);in[1]=1;dis[1]=0;while(!q.empty()){int x=q.front();q.pop();for(int i=head[x];i;i=nxt[i]){int y=ver[i];if(dis[x]+edge[i]+s<dis[y]&&e[y]){dis[y]=dis[x]+edge[i]+s;if(!in[y]){in[y]=1;q.push(y);}}}in[x]=0;}
}
void dfs(int x)
{vis[x]=1;for(int i=head[x];i;i=nxt[i]){int y=ver[i];if(!vis[y]) dfs(y);}
}
bool check(int x)
{for(int i=1;i<=n;i++){if(e[i]){memset(dis,0x3f,sizeof(dis));memset(vis,0,sizeof(vis));if(dfs_SPFA(i,x)) return 0;}}SPFA(x);if(dis[n]>=0) return 1;return 0;
}
int main()
{freopen("earth.in","r",stdin);freopen("earth.out","w",stdout);cin>>t;while(t--){memset(e,1,sizeof(e));memset(head,0,sizeof(head));memset(vis,0,sizeof(vis));c=0;n=read();m=read();for(i=1;i<=m;i++){int u,v,w;u=read();v=read();w=read();insert(u,v,w);}dfs(1);for(i=1;i<=n;i++){if(!vis[i]) e[i]=0;}for(i=1;i<=n;i++){if(e[i]){memset(vis,0,sizeof(vis));dfs(i);if(!vis[n]) e[i]=0;}}int l=-100000,r=100000,mid,ans;while(l<=r){mid=(l+r)/2;if(check(mid)){ans=dis[n];r=mid-1;}else l=mid+1;}if(ans>1e9) cout<<"-1"<<endl;else cout<<ans<<endl;}fclose(stdin);fclose(stdout);return 0;
}

转载于:https://www.cnblogs.com/LSlzf/p/10391754.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/363867.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

oracle 执行多条insert 语句

其实这是一个sqlserver的脚本改的。用脚本的原因是&#xff1a;当时我的oracle不能导入execl,也不能从别的数据库直接导入&#xff0c;最后就用脚本了。 insert all INTO TestA (ID, tbname, colname, coltxt, collen, coltype, coloper, colcontent) VALUES(1, A主表, ZHD0A00…

JUnit ExpectedException规则:超越基础

JUnit测试中有多种处理异常的方法。 正如我在以前的一篇文章中所写的那样 &#xff0c;我最好的方法是使用org.junit.rules.ExpectedException规则。 基本上&#xff0c;规则是用org.junit.Before &#xff0c; org.junit.After &#xff0c; org.junit.BeforeClass或org.junit…

sql 基本操作

数据库表的操作 SQL code ------------------------------列操作-------------------------------------添加列ALTERTABLEt ADDMycolumn intidentity(1,1)||notnulldefault(0) --删除列altertablet dropcolumnMycolumn --修改列altertablet altercolumnMycolumn varchar(20) no…

[EffectiveC++]item34:区分接口继承和实现继承

[EffectiveC]item34&#xff1a;区分接口继承和实现继承 转载于:https://www.cnblogs.com/jeanschen/p/3363569.html

web 上传文件到linux没权限,Javaweb上传文件到Linux 没有读写权限

一、 问题描述背景描述&#xff1a;0.saas-business-运营后台&#xff0c;website-网站页面。1.javaweb程序(saas-business)部署在linux系统 tomcat服务器下&#xff0c;使用该程序里面上传图片功能&#xff0c;上传图片至linux服务器挂载盘(共享盘)中/nfs/uploads/目录下。tom…

2008Beta 版AJAX的一个奇怪的问题

最近在用ASP.&#xff2e;&#xff25;&#xff34;做一个MIS系统&#xff0c;为了使页面有比较好的效果&#xff0c;减少刷新&#xff0c;用了AJAX控件&#xff0c;比如日历&#xff0c;水印等。 最主要的是用它来实现几个DropDownList控件之间的联动。起初问题是当也面加载时…

如何将IntelliJ项目添加到GitHub

尽管GitHub文档包含有关如何将现有GitHub项目添加到本地计算机的好信息&#xff0c;但是我对如何将本地计算机上的现有&#xff08;未版本化&#xff09;项目添加到GitHub的了解还很少。 这是我使用的步骤。 从IntelliJ 选择“ VCS”菜单->在版本控制中导入->在GitHub上…

REST-framework快速构建API--四部曲

代码目录结构&#xff1a; 一、使用原生APIView 使用rest-framework原生的APIView实现过程&#xff1a; 以url(r^books/$, views.BookView.as_view(),name"books")为例进行流程分析&#xff0c; 1、views.BookView.as_view()>APIView的as_view方法>父类【View】…

aix内核是linux,查看Linux及AIX硬件信息方法总结

一. CPU信息1. AIX1.查看CPU核心数&#xff1a;# pmcycles -m# pmcycles -mCpu 0 runs at 1900 MHzCpu 1 runs at 1900 MHzCpu 2 runs at 1900 MHzCpu 3 runs at 1900 MHz2.查看逻辑CPU个数# bindprocessor -q# bindprocessor -qThe available processors are: 0 1 2 33.查看CP…

Tomcat-部署多个项目(不同端口)

20190713 整理 参考文档 https://blog.csdn.net/chenchunlin526/article/details/78799772 如何在Tomcat服务中&#xff0c;为不同端口部署不同项目&#xff1f; https://jingyan.baidu.com/article/2f9b480ddda95e41cb6cc2a2.html Tomcat manager 配置 https://blog.csdn.ne…

JavaFX技巧2:使用Canvas API进行清晰绘图

当我最初开始使用Canvas API时&#xff0c;我注意到渲染代码的结果有些模糊&#xff0c;甚至更糟&#xff0c;不一致。 有些线条模糊&#xff0c;有些线条清晰。 来自Swing&#xff0c;我花了一些时间才意识到这是由JavaFX的坐标系引起的&#xff0c;该坐标系允许双精度渲染。 …

在阳光下歌唱

在阳光下歌唱 ——代腾飞 2007年11月27日 于成都 在寒冬迷雾阴霾已久的早上 突然迎来了一轮金色的太阳 清新的晨风轻抚着我的脸庞 一缕缕暖暖的阳光洒子身上 让人倍感清新爽朗欢心舒畅 昔日的忧伤也不再让人惆怅 往日的苦难也顿时被人遗忘 骑着车儿在阳光下尽情歌唱 我歌唱秋…

[Apple开发者帐户帮助]五、管理标识符(4)注册一个应用程序组

您需要注册一个或多个组才能启用应用组。 所需角色&#xff1a;帐户持有人或管理员。 在“ 证书”&#xff0c;“标识符和配置文件”中&#xff0c;从左侧的弹出菜单中选择操作系统。 在“标识符”下&#xff0c;选择“应用程序组”&#xff0c;然后单击右上角的“添加”按钮&…

JDK 8中的Oracle Drops Collection文字

在OpenJDK JEP 186上的一个帖子中&#xff0c;Oracle的Brian Goetz通知Oracle在JDK8中不会将集合文字用作语言功能。 集合文字是一种语法表达式形式&#xff0c;其求值形式为数组&#xff0c;列表或映射的聚合类型。 Project Coin提出了集合文字&#xff0c;这也补充了Java SE…

linux软件安装非系统盘,linux操作系统可不可以像安装windows软件一样在windows系统下的硬盘上安装...

linux操作系统可不可以像安装windows软件一样在windows系统下的硬盘上安装答案:2 信息版本&#xff1a;手机版解决时间 2020-07-24 14:13已解决2020-07-23 16:48打开linux操作系统iso压缩包,没有setup,听说要在虚拟机上安装&#xff0c;能不能不用虚拟机安装&#xff0c;在硬盘…

java中值传递和引用传递

1&#xff1a;按值传递是什么 指的是在方法调用时&#xff0c;传递的参数是按值的拷贝传递。 按值传递重要特点&#xff1a;传递的是值的拷贝&#xff0c;也就是说传递后就互不相关了。 2&#xff1a;按引用传递是什么 指的是在方法调用时&#xff0c;传递的参数是按引用进行传…

HTML5 Inline SVG

这是效果图&#xff1a; 1 <!DOCTYPE html>2 <html>3 <head>4 <meta content"text/html; charsetutf-8" http-equiv"Content-Type" />5 <title>geovindu svg</title>6 </head>7 <body>8 9 <svg width&…

【err】VIDEOIO ERROR: V4L: index 0 is not correct!Unable to connect to camera

前言 新到手一块板子&#xff0c;程序编译成功之后&#xff0c;运行出现错误&#xff0c;不能连接到摄像头。 问题 VIDEOIO ERROR: V4L: index 0 is not correct! Unable to connect to camera 查询系统摄像头接口 ubuntumyimx6ek200:~/build$ ls /dev/vi* /dev/video0 /dev/vi…

linux 卸载lv,Linux 软件安装、卸载、查询

平台构建及注意事项软件安装、配置等一、RPM 安装方法&#xff1a;# RPM -ivh XXX.rpm软件将被安装到缺省目录下。(不可指定安装路径&#xff01;)二、软件卸载&#xff1a;1、查询安装的软件注册名称&#xff1a;# rpm -q -a 部分可猜测软件名前缀 *2、卸载软件&#xff1a;#…

前端开发网络——Ajax(GET、POST)

ajax请求的过程 我们平时输入的网址&#xff0c;比如www.baidu.com&#xff0c;就会被解析成14.215.177.39这一串数字&#xff0c;然后发送请求给后台服务器&#xff08;客户端发送http请求&#xff09;。 服务器会确认你发送的是什么请求&#xff0c;需要请求什么东西&#xf…