【题目背景】

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

【问题描述】

  简单来说,它要从标号为 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=,f=;
while(c<''||c>''){
if(c=='-') f=-;
c=getchar();
}
while(c<=''&&c>=''){
w=w*+c-'';
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]=;
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 ;
dis[y]=dis[x]+edge[i]+s;
if(dfs_SPFA(y,s)) return ;
}
}
vis[x]=;
return ;
}
void SPFA(int s)
{
memset(dis,0x3f,sizeof(dis));
memset(in,,sizeof(in));
q.push();
in[]=;
dis[]=;
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]=;
q.push(y);
}
}
}
in[x]=;
}
}
void dfs(int x)
{
vis[x]=;
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=;i<=n;i++){
if(e[i]){
memset(dis,0x3f,sizeof(dis));
memset(vis,,sizeof(vis));
if(dfs_SPFA(i,x)) return ;
}
}
SPFA(x);
if(dis[n]>=) return ;
return ;
}
int main()
{
freopen("earth.in","r",stdin);
freopen("earth.out","w",stdout);
cin>>t;
while(t--){
memset(e,,sizeof(e));
memset(head,,sizeof(head));
memset(vis,,sizeof(vis));
c=;
n=read();
m=read();
for(i=;i<=m;i++){
int u,v,w;
u=read();
v=read();
w=read();
insert(u,v,w);
}
dfs();
for(i=;i<=n;i++){
if(!vis[i]) e[i]=;
}
for(i=;i<=n;i++){
if(e[i]){
memset(vis,,sizeof(vis));
dfs(i);
if(!vis[n]) e[i]=;
}
}
int l=-,r=,mid,ans;
while(l<=r){
mid=(l+r)/;
if(check(mid)){
ans=dis[n];
r=mid-;
}
else l=mid+;
}
if(ans>1e9) cout<<"-1"<<endl;
else cout<<ans<<endl;
}
fclose(stdin);
fclose(stdout);
return ;
}

NOIP模拟赛(by hzwer) T3 小奇回地球的更多相关文章

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

    [题目背景] 开学了,小奇在回地球的路上,遇到了一个棘手的问题. [问题描述] 简单来说,它要从标号为 1 的星球到标号为 n 的星球,某一些星球之间有航线. 由于超时空隧道的存在,从一个星球到另一个 ...

  2. NOIP模拟赛(by hzwer) T2 小奇的序列

    [题目背景] 小奇总是在数学课上思考奇怪的问题. [问题描述] 给定一个长度为 n 的数列,以及 m 次询问,每次给出三个数 l,r 和 P, 询问 (a[l'] + a[l'+1] + ... + ...

  3. NOIP模拟赛(by hzwer) T1 小奇挖矿

    [题目背景] 小奇要开采一些矿物,它驾驶着一台带有钻头(初始能力值 w)的飞船,按既定 路线依次飞过喵星系的 n 个星球. [问题描述] 星球分为 2 类:资源型和维修型. 1. 资源型:含矿物质量 ...

  4. 2.17NOIP模拟赛(by hzwer) T2 小奇的序列

    [题目背景] 小奇总是在数学课上思考奇怪的问题. [问题描述] 给定一个长度为 n 的数列,以及 m 次询问,每次给出三个数 l,r 和 P, 询问 (a[l'] + a[l'+1] + ... + ...

  5. 2.17NOIP模拟赛(by hzwer) T1 小奇挖矿

    [题目背景] 小奇要开采一些矿物,它驾驶着一台带有钻头(初始能力值 w)的飞船,按既定 路线依次飞过喵星系的 n 个星球. [问题描述] 星球分为 2 类:资源型和维修型. 1. 资源型:含矿物质量 ...

  6. NOIP模拟赛 经营与开发 小奇挖矿

    [题目描述] 4X概念体系,是指在PC战略游戏中一种相当普及和成熟的系统概念,得名自4个同样以“EX”为开头的英语单词. eXplore(探索) eXpand(拓张与发展) eXploit(经营与开发 ...

  7. NOIP模拟赛 by hzwer

    2015年10月04日NOIP模拟赛 by hzwer    (这是小奇=> 小奇挖矿2(mining) [题目背景] 小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿 ...

  8. 2015-9-13 NOIP模拟赛 by hzwer

    好老的题了,但是还是很有做头的. 总结 不吸氧看来确实是没法用stl的啊(set常数太大了,开O2也没过) SPFA没认真学,觉得有堆优化Dijkstra就天下无敌了,今天负边权教我做人 于是苦逼的只 ...

  9. 2015-9-13 NOIP模拟赛解题报告(by hzwer)

    小奇挖矿 「题目背景」 小奇要开采一些矿物,它驾驶着一台带有钻头(初始能力值w)的飞船,按既定路线依次飞过喵星系的n个星球. 「问题描述」 星球分为2类:资源型和维修型. 1.资源型:含矿物质量a[i ...

随机推荐

  1. java网络通信:netty

    Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速开发高性能.高可靠性的网络服务器和客户端程序. 也就是说,Netty 是一个基于NIO的客户,服务器端编程框架,使用Netty 可以确保 ...

  2. Java中判断两个列表是否相等

    CollectionUtils.isEqualCollection(final Collection a, final Collection b) CollectionUtils工具类中有一个查看两个 ...

  3. CentOS6.5 编译安装PHP5.6(apache模块)

    一.环境准备 1. 下载php源码包 # wget http://cn2.php.net/distributions/php-5.6.30.tar.gz # tar -xf php-5.6.30.ta ...

  4. Linux 系统安装 python

    Centos 7 Centos 7 安装 python3 (不要卸载python2 因为yum 要用) https://phoenixnap.com/kb/how-to-install-python- ...

  5. 6.文件所有权和权限----免费设置匿名----Windows键盘记录器----简介和python模块

    文件所有权和权限 touch --help cd Desktop mkdir Folder cd Folder clear touch Test1 Test2 Test3 Test4 ls ls -l ...

  6. tomcat启动失败的三种方法

    Tomcat启动失败的解决办法 1. 重复映射 用eclipse开发时,用Eclipse开发,新建了的servlet会有一个url-pattern声明: 这样就不需要再在web.xml中添加映射,如果 ...

  7. Luogu P5470 [NOI2019]序列

    题目 可以直接贪心,但是用模拟费用流推的话会更轻松. 首先有一个显然的建图方式: \(S\)到\(0\)流量为\(k\),费用为\(0\). \(0\)到\(a_i\)流量为\(1\),费用为\(-a ...

  8. Simpsons’ Hidden Talents

    Homer: Marge, I just figured out a way to discover some of the talents we weren’t aware we had. Marg ...

  9. DotNetCore知识栈

    #..NET Core提供的特性 1.开源.免费 2.轻量级.跨平台 3.组件化.模块化.IOC+Nuget.中间件 4.高性能 5.统一了MVC和WebAPI编程模型 a)  比如:ASP.NET ...

  10. 【问题解决方案】Xshell连接服务器并实现上传和下载文件

    参考链接: Xshell连接服务器并实现上传和下载文件 第一步:xshell登录完成 略 第二步: 在服务器安装lrzsz 如果服务器的操作系统是 CentOS,则输入命令[yum install l ...