【题目背景】

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

【问题描述】

  简单来说,它要从标号为 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去判断负权环即可。

【代码】

  1. #include <bits/stdc++.h>
  2. #define N 102
  3. #define M 200002
  4.  
  5. using namespace std;
  6.  
  7. int head[N],ver[M],nxt[M],edge[M],c,t,n,m,i,cnt[N],dis[N];
  8. bool e[N],vis[N],in[N];
  9. queue<int> q;
  10.  
  11. int read()
  12. {
  13. char c=getchar();
  14. int w=,f=;
  15. while(c<''||c>'')
  16. {
  17. if(c=='-') f=-;
  18. c=getchar();
  19. }
  20. while(c<=''&&c>='')
  21. {
  22. w=w*+c-'';
  23. c=getchar();
  24. }
  25. return w*f;
  26. }
  27.  
  28. void Insert(int x,int y,int z)
  29. {
  30. c++;
  31. ver[c]=y;
  32. edge[c]=z;
  33. nxt[c]=head[x];
  34. head[x]=c;
  35. }
  36.  
  37. bool dfs_SPFA(int x,int s)
  38. {
  39. vis[x]=;
  40. for(int i=head[x]; i; i=nxt[i])
  41. {
  42. int y=ver[i];
  43. if(dis[y]>dis[x]+edge[i]+s&&e[y])
  44. {
  45. if(vis[y]) return ;
  46. dis[y]=dis[x]+edge[i]+s;
  47. if(dfs_SPFA(y,s)) return ;
  48. }
  49. }
  50. vis[x]=;
  51. return ;
  52. }
  53.  
  54. void SPFA(int s)
  55. {
  56. memset(dis,0x3f,sizeof(dis));
  57. memset(in,,sizeof(in));
  58. q.push();
  59. in[]=;
  60. dis[]=;
  61. while(!q.empty())
  62. {
  63. int x=q.front();
  64. q.pop();
  65. for(int i=head[x]; i; i=nxt[i])
  66. {
  67. int y=ver[i];
  68. if(dis[x]+edge[i]+s<dis[y]&&e[y])
  69. {
  70. dis[y]=dis[x]+edge[i]+s;
  71. if(!in[y])
  72. {
  73. in[y]=;
  74. q.push(y);
  75. }
  76. }
  77. }
  78. in[x]=;
  79. }
  80. }
  81.  
  82. void dfs(int x)
  83. {
  84. vis[x]=;
  85. for(int i=head[x]; i; i=nxt[i])
  86. {
  87. int y=ver[i];
  88. if(!vis[y]) dfs(y);
  89. }
  90. }
  91.  
  92. bool check(int x)
  93. {
  94. for(int i=; i<=n; i++)
  95. {
  96. if(e[i])
  97. {
  98. memset(dis,0x3f,sizeof(dis));
  99. memset(vis,,sizeof(vis));
  100. if(dfs_SPFA(i,x)) return ;
  101. }
  102. }
  103. SPFA(x);
  104. if(dis[n]>=) return ;
  105. return ;
  106. }
  107.  
  108. int main()
  109. {
  110. freopen("earth.in","r",stdin);
  111. freopen("earth.out","w",stdout);
  112.  
  113. t=read();
  114.  
  115. while(t--)
  116. {
  117. memset(e,,sizeof(e));
  118. memset(head,,sizeof(head));
  119. memset(vis,,sizeof(vis));
  120.  
  121. c=;
  122.  
  123. n=read(),m=read();
  124.  
  125. for(i=; i<=m; i++)
  126. {
  127. int u=read(),v=read(),w=read();
  128.  
  129. Insert(u,v,w);
  130. }
  131.  
  132. dfs();
  133.  
  134. for(i=; i<=n; i++)
  135. {
  136. if(!vis[i]) e[i]=;
  137. }
  138.  
  139. for(i=; i<=n; i++)
  140. {
  141. if(e[i])
  142. {
  143. memset(vis,,sizeof(vis));
  144.  
  145. dfs(i);
  146.  
  147. if(!vis[n]) e[i]=;
  148. }
  149. }
  150.  
  151. int l=-,r=,mid,ans;
  152.  
  153. while(l<=r)
  154. {
  155. mid=(l+r)>>;
  156.  
  157. if(check(mid))
  158. {
  159. ans=dis[n];
  160. r=mid-;
  161. }
  162. else l=mid+;
  163. }
  164.  
  165. if(ans>1e9) cout<<"-1"<<endl;
  166. else cout<<ans<<endl;
  167. }
  168.  
  169. return ;
  170. }

P.S. 转载自LSlzf

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

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

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

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

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

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

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

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

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

  5. NOIP模拟赛(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. 【20170521校内模拟赛】热爱生活的小Z

    学长FallDream所出的模拟赛,个人感觉题目难度还是比较适中的,难度在提高+左右,可能比较接近弱省省选,总体来讲试题考查范围较广,个人认为还是很不错的. 所有试题如无特殊声明,开启-O2优化,时限 ...

随机推荐

  1. 剑指offer-面试题18-删除链表的节点-链表

    /* 题目:给定单向链表的头指针和一个节点指针,定义一个函数在O(1)时间内删除该节点. */ /* 思路: 将要删除的节点的下一个节点的value和next复制过来,删除下一个节点. 考虑两种特殊情 ...

  2. LeetCode 965. 单值二叉树 (遍历二叉树)

    题目链接:https://leetcode-cn.com/problems/univalued-binary-tree/ 如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树. 只有给定的树是 ...

  3. [CF1303F] Number of Components - 并查集,时间倒流

    有一个 \(n \times m\) 矩阵,初态下全是 \(0\). 如果两个相邻元素(四连通)相等,我们就说它们是连通的,且这种关系可以传递. 有 \(q\) 次操作,每次指定一个位置 \((x_i ...

  4. 中软国际首届嘉年华晚会 创新网络年会PK“春晚”

    随着新年脚步的来临,各大公司的年会陆续出炉,但是中软国际的首届嘉年华晚会,以创新网络年会和全国八地同步进行的模式,演绎不一样的互联网年会,简直可以PK“春晚”.IT届中最漂亮的美女热舞,程序员中最会唱 ...

  5. Linux C语言 文件操作

    打开函数 fopen 的原型如下. FILE * fopen(char *filename, char *mode); 返回值:打开成功,返回该文件对应的 FILE 类型的指针:打开失败,返回 NUL ...

  6. Chrome Extension 记录

    传递选定元素到内容脚本 内容脚本不能直接访问当前选中的元素.但是,任何使用 inspectedWindow.eval 来执行的代码都可以在 DevTools 控制台和命令行的 API 中使用.例如,在 ...

  7. 禁止PotPlayer自动添加同一目录内连续文件

    问题描述 默认情况下PotPlayer会自动向播放列表添加相似文件 统一目录下大量连续文件会被同时加载 解决办法 参数选项-基本-基本设置-相似文件策略 设置为仅打开选定的文件

  8. Centos下安装Oracle12c

    总结一次安装oracle的折腾血泪史环境准备 centos7 虚拟机VMware Workstation Pro14 IP:192.168.245.128(根据实际情况) 4G物理内存,8G虚拟内存, ...

  9. 曼孚科技:数据标注,AI背后的百亿市场

    ​ 1. 两年前,来自山东农村的王磊成为了一位数据标注员.彼时的他,工作内容非常简单且枯燥:识别图片中人的性别. 然而,一段时间之后,他注意到分配给他的任务开始变得越来越复杂:从识别性别到年龄,从框选 ...

  10. Mybatis的解析和运行原理

    Mybatis的解析和运行原理 Mybatis的运行过程大致分为两大步:第一步,读取配置文件缓存到Configuration对象,用以创建 SqlSessionFactory:第二步,SqlSessi ...